Florian Reichle


Angaben zu den Daten

Das verwendete Dataset des Projekts: https://www.kaggle.com/datasets/gregorut/videogamesales
Dies besteht aus den Daten von https://www.vgchartz.com/ für die Jahre 1980 bis 2016 und umfasst die Folgenden Spalten bzw.Daten.


Inhaltsverzeichnis

  1. Releaseanalyse
  2. Platformanalyse
  3. Publisheranalyse
  4. Genreanalyse
  5. Genreverteilung pro Jahr
  6. Publisher Genres
  7. Kritischer Rückblick

Thesen

Bevor wir mit der Analyse der Daten beginnen können Stellen wir erstmal ein paar Thesen bzw. Fragestellungen auf die wir im laufe des Projekts hinterfragen bzw beantworten wollen.


Daten und Librarys

Nach dem Vorstellen der Daten und dem aufstellen der initialen Thesen können wir nun mit dem einlesen der Daten beginnen.
Zusätzlich erstellen wir noch eine Farbpalette und importieren die Librarys

library(readr)
library(tidyverse)
library(forcats)
library(plotly)
library(knitr, warn.conflicts = FALSE, quietly=TRUE)
library(RColorBrewer)
library(stringr)
library(dygraphs)
library(xts)
suppressPackageStartupMessages(library(dplyr))
myPalette <- brewer.pal(10, "Paired")
vgsales <- read_csv("vgsales.csv")
Rows: 16598 Columns: 11
── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): Name, Platform, Year, Genre, Publisher
dbl (6): Rank, NA_Sales, EU_Sales, JP_Sales, Other_Sales, Global_Sales

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Videospiel releases

Videospiel releases im laufe der Jahre

Releases nach Anzahl

Unsere erste These war “Welche Jahre sind die besten in der Anzahl der releasten Games und Sales?” Um dieser Fragestellung auf den Grund zu gehen müssen wir zuerst einmal die Daten der Tabelle vgsales mithilfe der Funktion group_by(Year) anhand der Jahre Zusammenfassen. Nun erhalten wir eine nach den Jahren zusammengefasste Tabelle deren Einträge wir mit der Funktion dplyr::summarize(Anzahl =n()) abzählen und als Wert Anzahl abspeichern. Aufgrund der für diese analyse Fehlerhaften Daten verwenden wir noch die Funktion filter() um alle fehlenden Jahreseinträge sowie die Jahre 2020 und 2017 herauszufiltern. Letztere Jahre sind daher fehlerhaft, da der Datensatz 2016 erstellt wurde. Diese Daten speichern wir als data.frame in der Variable grouped ab. Im Folgenden verwenden wir ebenjenes data.frame um nur die Einträge Jahr und Anzahl zu selektieren und in der Variable filtered abzuspeichern. Die erhaltene Tabelle hat nun zwei Spalten: Jahr und Anzahl. Des Weiteren erstellen wir zwei weitere Variablen ax und aywelche beide eine Liste mit nur einem Attribut sind: “Title”. Nun verwenden wir plot_ly() um mithilfe der type = ‘scatter’ und mode = ‘lines’ Parameter ein Liniendiagramm zu erstellen. Außerdem nutzen wir die layout() funktion um einen Titel zu erstellen, sowie mithilfe unsere beiden Variablen ax und ay die Achsen zu beschriften.


grouped <- vgsales  %>%                                 
  group_by(Year) %>%
  dplyr::summarize(Anzahl =n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()


filtered <- grouped %>% select(Year,Anzahl)

ax <- list(
  title = "Jahr"
)

ay <- list(
  title = "Anzahl"

)

filtered %>%
plot_ly(x = ~Year, y = ~Anzahl, type = 'scatter', mode = 'lines', fill = 'tozeroy' ,colors = myPalette) %>% 
  layout(title="Anzahl der Spielereleases von 1980-2016",
         xaxis = ax,
         yaxis = ay
         )
NA

Betrachten wir einmal das entstandene Diagramm. Zwischen 1980 und 1993 sind hier kaum Unterschiede festzustellen und die Schwankungen können aufgrund der geringen Zahl der Veröffentlichungen (zwischen 14 und 49) vernachlässigt werden. Ab 1993 können wir dann ein stetiges Wachstum feststellen welches 1998 vorerst den Höchstwert erreicht. In den Jahren 1999 und 2000 geht die Anzahl erst einmal leicht zurück bevor sich der Wert bis 2002 von 349 auf 829 mehr als verdoppelt. Bis 2004 ist wiederum ein leichter Rückgang festzustellen auf welchem ein Stetiges Wachstum zum Höchstwert von 1428 (2008) sowie 1431 (2009) folgt. Danach folgt ein extremer und mit Unterbrechung von 2014 (582) und 2015 (614) stetiger Rückgang in den Release Zahlen auf einen Stand von 344 im Jahr 2016.

Sehen wir uns diese Zahlen einmal genauer an kommt die Frage auf Woran diese Extremen Zahlen in den Veröffentlichungen zurückzuführen sind? An diesem Punkt der Analyse können wir nur spekulieren die Spitzen könnten allerdings an den Veröffentlichungen großer, den Markt bestimmenden Plattformen wie der PS2/3, der Xbox und den Plattformen von Nintendo wie Gamecube oder Wii zurückzuführen sein. Hierzu aber später mehr.

Releases nach Verkaufszahlen

Um dem zweiten Teil der Fragestellung auf den Grund gehen zu können müssen wir erneut die Daten der Tabelle vgsales mithilfe der Funktion group_by(Year) anhand der Jahre Zusammenfassen. Nun erhalten wir wieder die nach den Jahren zusammengefasste Tabelle deren Einträge wir mit der Funktion dplyr::summarize(gr_sum = sum(Global_Sales)) zusammenfassen. Dem Aufmerksamen Leser wird auffallen das hier ein kleiner aber feiner Unterschied zum vorherigen Aufruf besteht. Statt Anzahl =n() nutzen wir hier gr_sum = sum(Global_Sales). Diese Funktion summiert alle Werte der Spalte Global_Sales auf und speichert den den Wert in die Spalte gr_sum. Aufgrund der für diese analyse weiterhin Fehlerhaften Daten verwenden wir erneut die Funktion filter() um alle fehlenden Jahreseinträge sowie die Jahre 2020 und 2017 herauszufiltern. Diese Daten speichern wir wieder als data.frame in der Variable grouped ab. Im folgenden verwenden wir ebenjenes data.frame um nur die Einträge Jahr und gr_sum zu selektieren und in der Variable filtered abzuspeichern. Die erhaltene Tabelle hat nun zwei Spalten: Jahr und gr_sum. Desweiteren erstellen wir erneut die Variablen ax und ay. Nun verwenden wir plot_ly() um mithilfe der type = ‘scatter’ und mode = ‘lines’ Parameter ein Liniendiagramm zu erstellen. Außerdem nutzen wir die layout() funktion um einen titel zu erstellen, sowie mithilfe unsere beiden Variablen ax und ay die Achsen zu beschriften.


grouped <- vgsales  %>%                                 
  group_by(Year) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()


filtered <- grouped %>% select(Year,gr_sum)

ax <- list(
  title = "Jahr"
)

ay <- list(
  title = " Verkäufe pro Jahr (in mio)"

)

filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'lines', fill = 'tozeroy' ,colors = myPalette) %>% 
  layout(title="Videospielverkäufe von 1980-2016",
         xaxis = ax,
         yaxis = ay
         )
NA

Betrachten wir nun das entstandene Diagramm fällt uns zuerst auf, dass es dem vorherigen recht ähnlich sieht. Dies ist kaum verwunderlich und stellt keinen nennenswerten Wissensgewinn da. Der wohl Nenneswerteste unterschied ist das Fehlen des Anstiegs, welcher in der Anzahl der Gamereleases zum Jahr 2015 festzustellen war. Durch den direkten Vergleich ist dies allerdings ein guter Zeitpunkt um uns mit unserer Zweiten These auseinanderzusetzen. “Werden heutzutage mehr Spiele Releast und Verkauft als noch 1980?”. Diese sehen wir aufjedenfall bestätigt obwohl Festzustellen ist, dass die besten Jahre sowohl in verkäufen als auch in der Anzahl die Jahre 2008 und 2009 waren. Dies Wirft natürlich die Frage auf was der Grund für diesen Verlauf ist und wäre ein Interessanter ansatz für eine weitere Arbeit.

Verkaufszahlen pro Spiel

Die Frage die Wir allerdings beantworten können ist “Werden neuere Spiele automatisch mehr Gekauft?”. Dafür kombinieren wir die beiden bereits Verwendeten ansätze. Wir fassen wieder die daten mithilfe von group_by(Year) anhand der Jahre Zusammen. Die erhaltene Tabelle fassen wir wieder mit dplyr::summarize(gr_sum = sum(Global_Sales)) zusammen. Diesmal nutzen wir jedoch eine kombination aus sum(Global_Sales) und n(). Wir addieren die Spalte Global_Sales, teilen dies durch die Anzahl der Einträge und speichern den Wert in die Spalte gamesales (gamesales = sum(Global_Sales)/n()). Danach filtern wir die Daten erneut und speichern sie als data.frame in grouped ab. Diesmal selektieren wie die Einträge der Spalte Jahr sowie gamesales und speichern sie in der Variable filtered ab. Zuletzt erstellen wir erneut die Variablen ax und ay und verwenden plot_ly() um mithilfe der type = ‘scatter’ und mode = ‘lines’ Parameter ein Liniendiagramm zu erstellen sowie die layout() funktion um einen titel zu erstellen und mithilfe unsere beiden Variablen ax und ay die Achsen zu beschriften.


grouped <- vgsales  %>%                                 
  group_by(Year) %>%
  dplyr::summarize(gamesales = sum(Global_Sales)/n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()


filtered <- grouped %>% select(Year,gamesales)

ax <- list(
  title = "Jahr"
)

ay <- list(
  title = "Verkäufe pro Spiel"

)

filtered %>%
plot_ly(x = ~Year, y = ~gamesales, type = 'scatter', mode = 'lines', fill = 'tozeroy' ,colors = myPalette) %>% 
  layout(title="Videospielverkäufe pro Spiel von 1980-2016",
         xaxis = ax,
         yaxis = ay
         )
NA

Sahen sich die beiden Diagramme für Anzahl und Verkaufszahlen noch recht ähnlich stellt sich hier ein deutlich unterschiedlicher Verlauf da. Ist der Wert zwischen 1980 (1.26) und 1983 (0.98) noch relativ gering steigt dieser Massiv für die Jahre 1984(3.59) und 1985(3.85) bevor er 1986(1.76) und 1987(1.35) wieder absinkt. Genauso schnell wie der wert abgesunken ist steigt er allerdings auch wieder auf 3.14(1988) bevor er 1989 den Höchststand mit 4.32 erreicht. Danach sinkt der wieder ab um sich nach einem kurzen ausschlag 1992 in den Jahren bis 2014 auf einen relativ stetigen Wert Zwischen 0.5 und 0.7 einzupendeln erst 2015 und 2016 sinkt dieser unter 0.5. Diese Extremen ausschläge in den Früheren Jahren lassen sich mit der Geringen anzahl der Spiele erklären. Einzelne gute laufende Spiele machen hier noch einen Großteil des Markts aus wohingegen sich neuere spiele, sowohl gegen eine Großzahl von bereits etablierten Spiele als auch eine große Anzahl neuer Releases, durchsetzen müssen.


Platform Analyse

Viedeospiele gibt es in den Unterschiedlichsten Farben und Formen. Was Sie jedoch alle gemeinsam haben ist, dass sie auf einem medium Gespielt werden. Sei es Sonys Playstation, Microsofts xBox, Nintendos Spielekonsolen wie die Wii oder der einfache desktop PC. Die Frage die Sich jeder Fan jedoch schonmal gestellt hat und über die häufig diskutiert wird ist welche ist die Beste? Da dies immer im Auge des Betrachters liegt versuchen wir zumindestens zu klären Welche Platform ist die beste in Anzahl verkäufen? Welche in Anzahl der Game Releases?. Zum beantworten dieser Frage ist der Vorhandene Datensatz nicht ganz optimal aber hierzu weiteres im Fazit.

Platformanalyse Global

nach Anzahl

Um sich einen guten Überblick über die Rankings der Plattformen zu verschaffen nutzen wir hier ein Paretodiagramm. Dies sind nach der Größe der Werte sortierte Säulendiagramme. Zum Erstellen des Diagramms brauchen wir zuerst einmal wieder unseren Datensatz den wir diesmal mithilfe des group_by Befehls anhand der Platform gruppieren. Danach nutzen wir erneut summarize(Anzahl =n() um die Einträge abzuzählen und den wert als Anzahl abzuspeichern. Um die Einträge der Anzahl nach zu sortieren nutzen wir zuerst den Befehl grouped[order(grouped$Anzahl),decreasing = FALSE] und weisen das Ergebnis der neuen Tabelle Ordered zu. Dieser Befehl sieht relativ komplex aus lässt sich jedoch recht einfach aufdröseln. Order sortiert die Tabelle nach der gegebenen Spalte und der Parameter decreasing = gibt an ob der größte Wert am Anfang oder Ende stehen soll. Das Dollar Zeichen selektiert hierbei die Spalte mit dem dahinterstehenden Name aus der vorher stehenden Tabelle getreu nach dem Schema Tabelle$Spalte. Danach müssen wir noch die Spalte Platform als faktor einlesen welches wir mit dem Befehl as_factor(ordered$Platform) tun. Danach erstellen wir unsere beiden Variablen ax und ay zur Achsenbeschriftung. Nun kommen wir zur eigentlichen Diagrammerstellung. Wir geben die Tabelle ordered weiter an plot_ly() und nutzen add_bars um ein Balkendiagramm zu erstellen. Der unterschied zwischen Balken und Paretodiagramm liegt hierbei in der Parameterübergabe. Schauen wir uns die relevanten Teile einmal genauer an. Der interessante Teil passiert hierbei bei der zuweisung der X-Achse und hier sehen wir auch den Grund für unsere vorherige umwandlung der Spalte Platform zu einem faktor. x=~fct_reorder(Platform,Anzahl, .desc=“true”),y=~Anzahl Wir nutzen den Befehel fct_reorder() um die Platformen nach der Anzahl sortiert her anzuordnen. Der erste Parameter ist hierbei die zu sortierende Spalte, der zweite die nach der sortiert werden soll. Der Parameter .desc steht descending und bestimmt wie sortiert werden soll, in unserem fall der größte Wert zuerst. Zu guter letzt geben wir dem Diagramm noch einen Namen, weisen die Farbpalette zu und setzen das Layout mit dem Titel sowie unseren beiden Achsenbeschriftungen.

grouped <- vgsales  %>% 
  group_by(Platform) %>% 
  summarize(Anzahl =n()) 

ordered <- grouped[order(grouped$Anzahl), decreasing = FALSE]
ordered$Platform <- as_factor(ordered$Platform)


ax <- list(
  title = "Platform"
)

ay <- list(
  title = "Anzahl"
)
ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Platform,Anzahl, .desc="true"),
           y=~Anzahl,
           name="Spieleanzahl pro Platform" ,colors = myPalette) %>% 
  layout(title="Spieleanzahl pro Platform",
         xaxis = ax,
         yaxis = ay
         
         )

Beim Betrachten des Diagramms erkennen wir das weder ganz alte noch ganz neue Platformen die Nase vorne haben. An den ersten beiden Stellen und weit abgeschlagen vom Rest der Platformen finden sich hier der DS von Nintendo (2163) und die Playstation 2 von Sony (2161). Dies ist weiter nicht Verwunderlich da beide auch die Konsolen sind die sich Weltweit am besten verkauft haben. Ein weiterer Grund für deren hohe Spieleanzahl ist vermutlich auch deren Stellung als Platzhirsche im Konsolen- bzw. Handheldmarkt. Weiterhin können wir erkennen das es meist die ältere Generationen einer Konsole sind die mehr Spiele haben. Die Playsatation 2 hat beispielsweise mehr Spiele als PS3 und PS4, die XboX360 mehr als die xBoxOne und der DS mehr als der 3DS. Dies scheint jedoch nicht auf die erste Generation zuzutreffen. Die Playstation hat mehr verkäufe als die PS4 aber weniger als PS3 und PS2. Die Xbox mehr als die XboxOne aber weniger als die Xbox360.

nach Verkaufszahlen

Schauen wir uns nun die Verkaufszahlen der Spiele der einzelnen Platformen an. Wir verwenden hier wieder ein Paretodiagramm und gehen ähnlich des vorherigen Diagramms vor. Zuerst nutzen wir wieder die group_by Funktion um nach den Platformen zu gruppieren. Da wir nun aber die Verkaufszahlen betrachten wollen nutzen wir summarize() auf die Global_Sales Spalte. Nun nutzen wir die rename() funktion um die so entstandene Spale sum(Global_Sales) in Global_Sales umzubenennen. Dies hat keinen weiteren Nutzen außer uns im späteren Verlauf die Referenzierung der Spalte einfacher zu machen. Um später nach dieser neu erstellten Spalte sortieren zu können müssen wir diese zuerst in einen Vector umwandeln. Dies tun wir mit dem Befehl grouped$Global_Sales<-as_vector(grouped$Global_Sales). Nun können wir die Tabelle sortieren und in der Variable ordered abspeichern ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]. Als letzten Schritt bevor es an die erstellung des Diagramms geht wandeln wir noch die Spalte Platform in einen Factor um ordered$Platform <- as_factor(ordered$Platform) und erstellen erneut unsere Achsenbeschriftungen ax und ay. Zur erstellung des Diagramms übergeben wir unsere ordered Tabelle an die plot_ly() funktion und nutzen add_bars um ein Balkendiagramm zu erstellen. Hier verwenden wir wieder die Parameter x=~fct_reorder(Platform,Global_Sales, .desc=“true”), y=~Global_Sales um den x wert, also die Platformen nach den Global Sales zu sortieren bevor wir den namen und die Farbe des Diagramms setzen. Zu guter Letzt benutzen wir noch die Layout funktion um dem Diagramm einen Titel zu geben und unsere beiden Achsenbeschriftungen zu erstellen.

grouped <- vgsales  %>% 
  group_by(Platform) %>% 
  summarize(sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Platform <- as_factor(ordered$Platform)


ax <- list(
  title = "Platform"
)

ay <- list(
  title = "Verkaufszahlen (in mio)"

)


ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Platform,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="Verkaufszahlen nach Platform" ,colors = myPalette) %>% 
  layout(title="Verkaufszahlen nach Platform",
         xaxis = ax,
         yaxis = ay
         )

Schauen wir uns das Entstandene Diagramm einmal auf fallen uns direkt zwei Dinge auf. Zum einen fehlt der Nintendo DS auf dem Spitzenplatz zusammen mit der PS2 und ist nur auf Platz 5, zum anderen ist der Unterschied zwischen den Spitzenplätzen bzw dem Spitzenplatz und dem rest der top 5 deutlich geringer. Waren es bei der Spieleanzahl noch fast 40% unterschied zwischen platz 1/2 und platz 3-4 so sind es hier nur knapp 20%. Die Restlichen plätze der Top 5 sind allerdings größtenteils gleich geblieben. Zusätzlich zum absacken des Nintendo DS von platz 1 auf platz 5 hat nur die XboX360 ihre Position in der Rangliste verändert.

Haben Ältere Platformen Automatisch mehr Spiele und Verkäufe?

Beim Betrachten beider Diagramme oder sogar nur einem der Diagramme erkennt der Aufmerksame Betrachter relativ schnell das hier keine Pauschalantwort auf diese Fragestellung möglich ist. Dies ist aber irgendwie zu erwarten gewesen es gibt so viele Faktoren die den Erfolg einer bestimmten Platform bestimmen und es ist unmöglich dieses an einem Faktor festzulegen. Wwelche Frage wir allerdings beantworten konnten, zumindestens teilweise, ist die Frage nach der “besten Platform. Die PS2 ist sowohl weit oben in der Spieleanzahl, als auch Spitzenreiter in den Gamverkäufen. Der Nintendo DS ist zwar in der Spieleanzahl sogar knapp vor der PS2 in den verkäufen aber weit abgeschlagen auf Platz 5. Ausschlaggebender als vergleichsargument wäre jedoch die Anzahl der Verkauften Spiele pro Spiel doch weiteres hierzu im Ausblick in die Zukunft

Offensichtlich ist ein Datensatz zu Anzahl der Spieleverkäufe vorallem ein so lückenhafter nicht optimal aber dazu weiteres im Fazit.


Regionale Unterschiede in den Verkaufszahlen der Platformen

Da wir nun geklärt haben welche Platformen die Nase vorne haben wäre es doch Interessant herauszufinden ob es Regionale unterschiede gibt. Favorisieren verschiedene Regionen verschiedene Platformen? Verkaufen die Regionenheimischen Platformen automatisch auch die meisten Spiele?

Hierbei können wir natürlich nur die Verkaufszahlen heranziehen. Theoretisch wäre auch ein Vergleich in anzahl der Spiele möglich würde aber diese Arbeit Sprengen da der Datensatz diese Informationen nicht ohne weiteres hergibt. Zum Beantworten dieser Frage benutzen wir erneut Paretodiagramme und um sich einen Groben überblick zu schaffen Kreisdiagramme. Diese haben ihre eigenen Probleme bieten uns aber ein gutes Tool zur groben übersicht über die Prozentualverteilung der Konsolen und bringt etwas Abwechslung in diese bisher sehr Balkendiagramm lastige ausarbeitung.

Einzuwenden hierbei ist, dass die Regionen natürlich unterschiedlich viele Einwohner haben.Ein vergleich der absoluten Saleswerte ist hierbei natürlich nur wenig ausschlaggebend zeigt aber einen generellen beliebtheitstrend der Konsolen in den einzelnen Regionen auf.

Platformvergleich

Balkendiagramme

Die Erstellung der Paretodiagramme werde ich an dieser Stelle nicht mehr genauer erläutern, da das Grundprinzip weiterhin das gleiche bleibt einziger unterschied zwischen den verschiedenen Diagrammen ist hierbei der wert in der summarize Funktion summarize(sum(EU_Sales)) EU_Sales für EU NA_SALES für US und JP_SALES für Japan sowie der Titel und die Achsenbeschriftungen. Eine genauere Erläuterung zur Erstellung von Paretodiagrammen gibt es hier.

Europa

grouped <- vgsales  %>% 
  group_by(Platform) %>% 
  summarize(sum(EU_Sales))  %>%
rename(
    Global_Sales = "sum(EU_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Platform <- as_factor(ordered$Platform)


ax <- list(
  title = "Platform"
)

ay <- list(
  title = "EU verkäufe (in mio)"

)


ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Platform,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="EU Verkaufszahlen pro Platform" ,colors = myPalette) %>% 
  layout(title="EU Verkaufszahlen pro Platform",
         xaxis = ax,
         yaxis = ay
         )

Hatte im Globalen durchschnitt die PS2 noch deutlich die Nase vorne ist in EU die PS3 (343.71) noch vor der PS2 (339.29) und diese haben beide noch einen Recht weiten Vorsprung auf Platz 3 (280.58) und 4 (268.38) welche respektive von der Xbox360 und der Wii belegt werden. Die Playstation 1 (213.6) sichert sich in Europa einen platz in den top 5 und auch die PS4 (123.7) rückt einen Platz nach Vorne. Den wohl größten Sprung legt allerdings der PC (139.68) hin. Ist dieser Global noch auf Platz 10 so belegt er in Europa platz 7. Auch außerhalb der Top 10 gibt es einige verschiebungen aufgrund des eher Geringeren Marketshares sehen wir hier allerdings von einer genaueren Analyse ab. Zusammenfassend können wir also sagen das Europa Sony konsolen sowie den Pc überdurchschnittlich gerne Nutzen.

Nord-Amerika

grouped <- vgsales  %>% 
  group_by(Platform) %>% 
  summarize(sum(NA_Sales))  %>%
rename(
    Global_Sales = "sum(NA_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Platform <- as_factor(ordered$Platform)


ax <- list(
  title = "Platform"
)

ay <- list(
  title = "NA verkäufe (in mio)"

)


ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Platform,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="NA Verkaufszahlen pro Platform" ,colors = myPalette) %>% 
  layout(title="NA Verkaufszahlen pro Platform",
         xaxis = ax,
         yaxis = ay
         )

Im direkten Vergleich mit EU fällt hier sofort ins Auge, dass die Playstation 2 (583.84) zwar weiterhin von dem ersten Platz verdrängt wurde, Microsofts Xbox360 (601.05) hier Sonys Playstation 3 (392.26) allerdings auf dem ersten Platz ablöst. Auch die Wii (507.71) hat erkennbar mehr Verkäufe als noch in Europa. PS4 (96.8) und PC (93.28) spiele verkaufen sich in Nord-Amerika deutlich weniger als in Europa wohingegen die Restlichen Platformen größtenteils Ähnlich verteilt bleiben.

Japan

grouped <- vgsales  %>% 
  group_by(Platform) %>% 
  summarize(sum(JP_Sales))  %>%
rename(
    Global_Sales = "sum(JP_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Platform <- as_factor(ordered$Platform)


ax <- list(
  title = "Platform"
)

ay <- list(
  title = "JP verkäufe (in mio)"

)


ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Platform,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="JP Verkaufszahlen pro Platform" ,colors = myPalette) %>% 
  layout(title="JP Verkaufszahlen pro Platform",
         xaxis = ax,
         yaxis = ay
         )

Japan ist wohl der größte Ausreißer der drei Regionen. Hier führt der Nintendo DS (175.57) die Liste an. Auch der Abstand auf Platz 2 ist hier größer als in den anderen Regionen welcher nicht von der Playstation 2 (Platz 3) sondern der Playstation 1 belegt wird. Weit abgeschlagen ist die PS2 (139.2 mio) von der PS1(139.82) jedoch nicht. Sonys beide Konsolen sind auch die einzigen nicht Nintendo konsolen in den Top 7. Allegemein ist hier ein großer Fokus auf Japanische unternehmen zu erkennen wenn man bedenkt das die erste, nicht japanische konsole, die Xbox 360 (12.43) auf Platz 17 ist. Japanische hersteller sind in der Spieleindustrie weit verbreitet ein so extremes Verhältnis ist Global jedoch nicht die Norm. Schauen wir uns das ganze einmal genauer als Kreisdiagramme an um die Verhältnise etwas deutlicher zu machen.

Kreisdiagramme

Da wir bisher noch keine Kreisdiagramme genutzt haben schauen wir uns erst mal die Unterschiede in der Diagrammerstellung an bevor wir uns auf die Analyse ebenjener Diagramme stürzen. Der einfachheit halber schauen wir uns das ganze nur am Beispiel Europa an, die anderen Diagramme unterscheiden sich aber nur in dem Wert in der summarize funktion sowie den Achsen- und der Diagrbeschriftung. Der Grundaufbau der Diagramm erstellung ist hier wieder ähnlich wie bei den Paretodiagrammen. Zuerst gruppieren wir die Daten, sortieren sie nach Anzahl der Verkäufe und erstellen unsere Achsenbeschriftungen. Danach zum interessanten Teil der Diagrammerstellung welcher sich eigentlich auch nicht groß von den Paretodiagrammen unterscheidet. Wir übergeben unsere Sortierten Daten an Plot_ly() und verwenden die Funktion add_pie mit entsprechenden Parametern zur Diagramm erstellung. Diese unterscheiden sich etwas von den Paretodiagrammen. Values sind hierbei die Werte, die die Größe und labels die Bezeichnung der “Kuchenstücke” festlegen. Der letzte interessante Parameter ist textinfo mit welchem Festgelegt wird was als text in den Abschnitten aufgeführt wird. In unserem Beispiel nutzen wir hier textinfo=‘label+percent’ umd sowohl die Bezeichnungen als auch den Genauen Prozentwert anzuzeigen.

Europa

grouped <- vgsales  %>% 
  group_by(Platform) %>% 
  summarize(sum(EU_Sales))  %>%
rename(
    Global_Sales = "sum(EU_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Platform <- as_factor(ordered$Platform)


ax <- list(
  title = "Platform"
)

ay <- list(
  title = "EU verkäufe (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Platform,textinfo='label+percent',  textposition = 'inside',
           name="EU Verkaufszahlen pro Platform" ,colors = myPalette) %>% 
  layout(title="EU Verkaufszahlen pro Platform",
         xaxis = ax,
         yaxis = ay,
         showlegend = FALSE,
         autosize = F
         )

Ohne direkte Globale vergleichsdiagramme können wir hier im ersten Schritt noch keine großartigen Aussagen treffen werden aber im späteren Verlauf auf diese eingehen. Was wir hier allerdings gut erkennen Können ist, dass die größten vier Platformen hier 50.5% der Gesamtverkäufe ausmachen und Sonys Konsolen sogar 28%.

Nord-Amerika

grouped <- vgsales  %>% 
  group_by(Platform) %>% 
  summarize(sum(NA_Sales))  %>%
rename(
    Global_Sales = "sum(NA_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Platform <- as_factor(ordered$Platform)


ax <- list(
  title = "Platform"
)

ay <- list(
  title = "NA verkäufe (in mio)"

)


ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Platform,textinfo='label+percent', textposition = 'inside',
           name="NA Verkaufszahlen pro Platform" ,colors = myPalette) %>% 
  layout(title="NA Verkaufszahlen pro Platform",
         xaxis = ax,
         yaxis = ay,
         showlegend = FALSE,
         autosize = F
         )

Beim betrachten des Diagrammes für Amerika sehen wir das die Top 4, welche weiterhin aus XboX360 Wii Ps2 und PS3 bestehen, nur noch 47.53% ausmachen. Größter Verlierer sind hier Sonys Konsolen, welche nur noch 22.23% ausmachen.

Japan

grouped <- vgsales  %>% 
  group_by(Platform) %>% 
  summarize(sum(JP_Sales))  %>%
rename(
    Global_Sales = "sum(JP_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Platform <- as_factor(ordered$Platform)


ax <- list(
  title = "Platform"
)

ay <- list(
  title = "JP verkäufe (in mio)"

)


ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Platform,textinfo='label+percent', textposition = 'inside',
           name="JP Verkaufszahlen pro Platform" ,  rotation = 40, colors = myPalette) %>% 
  layout(title="JP Verkaufszahlen pro Platform",
         xaxis = ax,
         yaxis = ay,
         showlegend = FALSE,
         autosize = F
         
         )

In Japan machen die Top 4 44.23% aus bestehen aber bis auf die PS2 aus gänzlich anderen Konsolen. Da Sonys PS3 von der PS ersetzt wird halten diese weiterhin 21.6% der Top 4. Nintendo holt sich hier jedoch den Größten Anteil mit 22.63%. Ein vergleich dieser Werte ist jedoch, wie bereits im Vorspann der Platform Rankings erwähnt mit Problemen gehaft. Genaueres hierzu wie bereits erwähnt im Fazit.


Platform Verkaufszahlen im laufe der Jahre

Nachdem wir uns die Platform verteilung angeschaut haben stellt sich die Frage ob es im laufe der Jahre unterschiede in den Verkäufen gibt.

Um uns dies anzuschaun verwenden wir eine neue art der Grafik die wir bisher noch nicht verwendet haben. Zum erstellen der Grafik gruppieren wir zuerst wieder unsere Daten und addieren die werte der Sales pro Jahr und Platform auf. ZUsätzlich zum Filter der ungültigen Jahre filter wir allerdings alle Summen mit weniger als 60 mio in Sales. Dies ist um eine Überladung des Diagramms zu verhindern führt aber zu anderen Problemen. Neu in der erstellung dieses Diagramms sind auch die befehle arrange() und slice(). Arrange sortiert die Tabelle anhand der gegebenen Spalte in unserem fall ist das die Summe der Globalen verkäufe. Slice entfernt alle Spalten bis auf jene, welche wir verwenden wollen. Neu bei der Diagamm erstellung sind hier die Parameter mode = ‘none’ sowie stackgroup = ‘one’ welche die hier zu sehende Grafik erzeugen.


grouped <- vgsales  %>%                                 
  group_by(Year, Platform) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017')  %>% filter(gr_sum>60)%>%
  as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
grouped <- grouped %>%arrange(desc(gr_sum)) %>% 
  group_by(Year, Platform) %>%
  slice(1:3)

filtered <- grouped %>% select(Year,Platform,gr_sum)
ax <- list(
  title = "Jahr"
)

ay <- list(
  title = "verkäufe pro Platform (in mio)"

)


filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', stackgroup = 'one',color = ~Platform ,colors = myPalette)%>% 
  layout(title="Verkäufe pro Platform von 1980-2016",
         xaxis = ax,
         yaxis = ay
         )
NA

Im ersten Moment ist die Grafik sehr verwirrend aber dröseln wir das ganze einmal genauer auf. Zuerst einmal fällt auf, dass die Jahre 1980-1988 sowie 1990-1005 und 2016 fehlen. Dies liegt an den oben gewählten Filtern und den in den Jahren pro Plattform gemessen zu geringen Verkaufszahlen. Zwischen den Jahren 1996 und 2000 ist hier nur die Playstation, welche 1994 veröffentlicht wurde zu erkennen. Im Jahre 2000 wird diese dann von der Playstation 2, welche am 04.03.2000 releast wurde abgelöst. Auch der Gameboy Advanced hier in den Jahren 2000-2003 sowie 2004 zu erkennen, obwohl dieser Global erst Mitte des Jahres 2001 releast wurde.2004 wird die Playstation 2 dann von der Xbox, welche am 22.02.2002 erstmals veröffentlich wurde, kurzzeitig abgelöst bevor die Wii(02.12.2006) mit nur einem Verkaufsmonat des Jahres 2006 die Führung übernimmt. Auch die Verkaufszahlen des Nintendo DS (02.12.2004) sind in den Jahren 2005-2010 gut erkennbar. Die XboX360 (10.12.2005) übernimmt ab 2007 den ersten Platz der Rangliste und wird erst 2014 von der PS4(15.11.2013) abgelöst.

Allgemein ist hier ein Trend erkennbar. Meist verkaufen Platformen wie zu erwarten einige Zeit nach Release die meisten Spiele. Erstaunlicherweise ist dies jedoch nicht kurz nach Release sondern z.T. erst einige Jahre später. Interessant währe hier eine detailliertere analyse aber weiteres dazu hier.


Publisher Vergleich

Nachdem wir uns nun eine Übersicht über die Platformen gemacht haben wäre es doch interessant zu wissen ob sich neben bestimmten Platformen auch bestimmte Entwickler/Publisher häufen. Anzunehmen ist hierbei das Namenhafte Publisher wie EA und Nintendo die Liste anführen. Hierzu verwenden wir wiederum Paretodiagramme. Eine genauere erklärung zur erstellung ebenjener gibt es hier. Einzige neuerung in diesem abschnitt ist das Kürzen der Namen um die Begriffe “Entertainment”, “Interactive”, “Game”, “Games” und “Studios” da dies die Namen nur unnötig verlängert. Um dies zu erreichen mutzen wir die Funktion str_remove_all() auf die Spalte Publisher.

Publisher

nach Anzahl

grouped <- vgsales  %>% 
  group_by(Publisher) %>% 
  summarize(Anzahl =n()) %>%  
  filter(Anzahl>100) %>% filter(Publisher!="Unknown")




PublisherSales <- vgsales %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)


ordered <- grouped[order(grouped$Anzahl), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)


ax <- list(
  title = "Publisher"
)

ay <- list(
  title = "Anzahl"
)
ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Publisher,Anzahl, .desc="true"),
           y=~Anzahl,
           name="Spiele Anzahl pro Publisher"
           ,colors = myPalette) %>% 
  layout(title="Spiele Anzahl pro Publisher",
         xaxis = ax,
         yaxis = ay
         
         )

Betrachten wir zuerst einmal die Anzahl der Spielereleases. Wenig überaschend ist hier EA (1351), mit jährlich veröffentlichenden namenhaften Spielen wie FIFA und Madden NFL sowie anderen bekannten Reihen wie Need for Speed, Battlefield oder Sims, anführer der Liste. An zweiter stelle befindet sich Activision (975) die unter anderem Spiele wie World of Warcraft, die Diablo reihe sowie Candy Crush entwickelten. Zum Zeitpunkt der Erstellung dieser Arbeit sind diese noch ein eigener Konzern werden allerdings vorausichtlich 2023 Teil von Microsoft. Darauf folgen in kurzen abständen Ubisoft (921), welche für Assasins Creed, Rainbox six oder Anno bekannt sind, sowie THQ mit 715 (Gothic, Darksiders, TitanQuest). Auch Nintendo (703) mit Mario, Pokemon und Zelda sowie Sony (638), bekannt durch die Gran Tourismo und Uncharted Reihe sowie The last of Us, sind nicht weit abgeschlagen. Den letzten platz der Top Publisher belegt Take Two, welche für GTA, Borderlands und Civilization bekannt sind, mit 413.

nach Verkaufszahlen

grouped <- vgsales  %>% 
  group_by(Publisher) %>% 
  summarize(Anzahl =n(),sum(Global_Sales)) %>%
  filter(Anzahl>100) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    )

PublisherSales <- vgsales %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)


ax <- list(
  title = "Publisher"
)

ay <- list(
  title = "Verkäufe (in mio)"

)


ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Publisher,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="Verkaufszahlen pro Publisher"
           ,colors = myPalette) %>% 
  layout(title="Verkaufszahlen pro Publisher",
         xaxis = ax,
         yaxis = ay
         )

Beim Betrachten der Verkaufszahlen fällt hier direkt die diskrepanz zwischen Anzahl der Spielereleases und Anzahl der Spieleverkäufe auf. Im gegensatz zu der Anzahl der Spiele (bei dem Nintendo nur auf platz 6 Sitz) dominiert Nintendo(1.786 mrd) in Sales. EA (1.1 mrd), welche noch mit Abstand die meisten spielreleases hatten sind in den Verkäufen nur noch mit deutlichem Abstand auf Platz 2. Auch die anderen Plätze verändern sich leicht die Unterschiede sind hier jedoch deutlich geringer als bei Nintendo und EA. Interessant wäre hierzu vielleicht noch ein direkter vergleich zwischen Anzahl und Sales aber genaueres dazu im Fazit


Publisher Ranking nach Region

Nachdem wir uns einen Allgemeinen Überblick über die Publisher gemacht haben betrachten wir die Regionalen unterschiede in den Verkaufszahlen. Hierzu verwenden wir erneut die Bereits bekannten Shemata der Pareto- und Kreisdiagramm kombo. Einen Refresher für die Erstellung ebenjener Diagramme gibt es via den Entsprechenden Links.

Ranking nach Region

Balkendiagramme

Europa

grouped <- vgsales  %>% 
  group_by(Publisher) %>% 
  summarize(Anzahl =n(),sum(EU_Sales)) %>%
  filter(Anzahl>100) %>%
rename(
    Global_Sales = "sum(EU_Sales)"
    )

PublisherSales <- vgsales %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)


grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)


ax <- list(
  title = "Publisher"
)

ay <- list(
  title = "EU verkäufe (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Publisher,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="EU Verkaufszahlen pro Publisher"
           ,colors = myPalette) %>% 
  layout(title="EU Verkaufszahlen pro Publisher",
         xaxis = ax,
         yaxis = ay
         )

Im vergleich zu den Globalen Verkaufszahlen fällt hier auf das EA (371.27 mio) deutlich dichter hinter Nintendo(418.74) auf dem Zweiten Platz ist. Der Abstand zwischen EA und Activision (215.53) ist dementsprechend auch deutlich größer. Die restlichen werte unterscheiden sich aber kaum.

Nord Amerika

grouped <- vgsales  %>% 
  group_by(Publisher) %>% 
  summarize(Anzahl =n(),sum(NA_Sales)) %>%
  filter(Anzahl>100) %>%
rename(
    Global_Sales = "sum(NA_Sales)"
    )

PublisherSales <- vgsales %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)

grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)


ax <- list(
  title = "Publisher"
)

ay <- list(
  title = "NA verkäufe (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Publisher,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="NA Verkaufszahlen pro Publisher"
           ,colors = myPalette) %>% 
  layout(title="NA Verkaufszahlen pro Publisher",
         xaxis = ax,
         yaxis = ay
         )

Auch in Nord Amerika kann EA(595.07) leicht größere Verkaufszahlen im vergleich mit Nintendo (816.87) als noch Global verbuchen. Im gegensatz zu Europa scheint jedoch Activision (429.7) in Amerika deutlich beliebter zu sein. Die weiteren Publisher sind auch weiterhin nicht Relevant.

Japan

grouped <- vgsales  %>% 
  group_by(Publisher) %>% 
  summarize(Anzahl =n(),sum(JP_Sales)) %>%
  filter(Anzahl>100) %>%
rename(
    Global_Sales = "sum(JP_Sales)"
    )

PublisherSales <- vgsales %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)

grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)


ax <- list(
  title = "Publisher"
)

ay <- list(
  title = "JP verkäufe (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Publisher,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="JP Verkaufszahlen pro Publisher"
           ,colors = myPalette) %>% 
  layout(title="JP Verkaufszahlen pro Publisher",
         xaxis = ax,
         yaxis = ay
         )

Japan Zeigt hier wohl den Deutlichsten unterschied auf. Nintendo (455.42) Dominiert hier die Verkaufszahlen mit der mehr als 6 fachen menge an verkäufen als Sony (74.1) welche sich den 2. Platz sichern. Die anderen Publisher sind alle fast gleich irrelevant in Japan.

Kreisdiagramme

Europa

grouped <- vgsales  %>% 
  group_by(Publisher) %>% 
  summarize(Anzahl =n(),sum(EU_Sales)) %>%
  filter(Anzahl>100) %>%
rename(
    Global_Sales = "sum(EU_Sales)"
    )

PublisherSales <- vgsales %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)

grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)


ax <- list(
  title = "Publisher"
)

ay <- list(
  title = "EU verkäufe (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Publisher,
           name="EU Verkaufszahlen pro Publisher"
          ,colors = myPalette) %>% 
  layout(title="EU Verkaufszahlen pro Publisher",
         xaxis = ax,
         yaxis = ay
         )

Im vergleich zu den Globalen Verkaufszahlen fällt hier auf das EA (23.7%) deutlich dichter hinter Nintendo(26.7%) auf dem Zweiten Platz ist. Der Abstand zwischen EA und Activision (13.7%) ist dementsprechend auch deutlich größer. Die restlichen werte unterscheiden sich kaum.

Nord-Amerika

grouped <- vgsales  %>% 
  group_by(Publisher) %>% 
  summarize(Anzahl =n(),sum(NA_Sales)) %>%
  filter(Anzahl>100) %>%
rename(
    Global_Sales = "sum(NA_Sales)"
    )

PublisherSales <- vgsales %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)

grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)


ax <- list(
  title = "Publisher"
)

ay <- list(
  title = "NA verkäufe (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Publisher,textinfo='label+percent',
           name="NA Verkaufszahlen pro Publisher"
          ,colors = myPalette) %>% 
  layout(title="NA Verkaufszahlen pro Publisher",
         xaxis = ax,
         yaxis = ay
         )

Auch in Nord Amerika kann EA(21.3%) leicht größere Verkaufszahlen im vergleich mit Nintendo (29.3%) als noch Global verbuchen diese sind jedoch geringer als noch in Europa. Im gegensatz zu Europa scheint jedoch Activision (15.4%) in Amerika deutlich beliebter zu sein. Die weiteren Publisher sind auch weiterhin nicht Relevant.

Japan

grouped <- vgsales  %>% 
  group_by(Publisher) %>% 
  summarize(Anzahl =n(),sum(JP_Sales)) %>%
  filter(Anzahl>100) %>%
rename(
    Global_Sales = "sum(JP_Sales)"
    )

PublisherSales <- vgsales %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)

grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)


ax <- list(
  title = "Publisher"
)

ay <- list(
  title = "JP verkäufe (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Publisher,
           name="JP Verkaufszahlen pro Publisher"
          ,colors = myPalette) %>% 
  layout(title="JP Verkaufszahlen pro Publisher",
         xaxis = ax,
         yaxis = ay
         )

Japan Zeigt hier wohl den Deutlichsten unterschied auf. Nintendo (80.1%) Dominiert hier die Verkaufszahlen mit der mehr als 6 fachen menge an verkäufen als Sony (13%) welche sich den 2. Platz sichern. Die anderen Publisher sind mit weniger als 2.5% alle fast gleich irrelevant in Japan.

Zwischen EU und US lassen sich hier kaum Unterschiede feststellen in Japan hingegen ist eine deutliche verschiebung zu erkennen. Japanische Publisher führen hierbei die Liste an und drängen andere große unternehmen von den Top spots. Dementsprechend können wir schlussfolgern das manche Regionen, vorallem Japan welches die kleinste Region ist, deutliche vorlieben in spielen bestimmter Publisher haben, welche von der Globalen norm Abweichen. Eine Genauere Analyse von Europa und Nord Amerika durch unterteilung in Länder/Staaten währe hier vermutlich deutlich interessanter wird von den Daten jedoch leider nicht angeboten.


Genreverteilung der Videospiele nach Anzahl

Da wir uns nu klar geworden sind, dass es bestimmte Publisher gibt, die beliebter sind als andere wäre es interessant herauszufinden ob bestimmte Spiele Genres beliebter sind als andere. Hierzu vergleichen wir zuerst einmal die Genres nach anzahl der Spielereleases und verwenden erneut ein Pareto- und Kreisdiagramm. Anzumerken ist hierbei jedoch das Spiele meist mehr als einem Genre angehören in diesem Datensatz ist jedoch immer nur eins angegeben.

Genre nach Anzahl

Balkendiagramm

grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(Anzahl =n())

grouped$Anzahl<-as_vector(grouped$Anzahl)
ordered <- grouped[order(grouped$Anzahl), decreasing = FALSE]
ordered$Genre <- as_factor(ordered$Genre)


ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Anzahl"

)

ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Genre,Anzahl, .desc="true"),
           y=~Anzahl,
           name="Videospielanzahl nach Genre"
           ,colors = myPalette) %>% 
  layout(title="Videospielanzahl nach Genre",
         xaxis = ax,
         yaxis = ay
         )
NA

Der Anführer der Liste ist mit deutlichem Abstand Action (GTA,Bloodborne) mit 3316. Auf dem Zweiten platz findet sich Sports (2346) mit reihen wie FIFA und NBA2k. Den dritten Platz belegt ein Genre das aus vielen verschiedenen Genren besteht die in dieser Liste nicht aufgeführt werden mit 1739. Misc beinhaltet spiele wie Just Dance (Musik/Rhythmus) oder Minecraft ein Sandbox Survival game. Danach kommen mit geringerem Abstand der Reihe nach Role-Playing (Witcher, The Elder Scrolls) mit 1488, Shooter (Call of Duty, Doom) mit 1310, Adventure (God of War, Life is Strange) mit 1286 und Racing (Gran Tourismo, Forza) mit 1249. Danach folgen mit einem größeren Abstand Platform (Super Mario, LittleBigPlanet) mit 886, Simulation (Sims, Microsoft Flight Simulator) mit 867 sowie Fighting (Tekken, Super Smash Bros) mit 884. Zu guter letzt fehlen noch Strategy (Age of Empires, Civilisation) mit 681 sowie Puzzle (Portal,Tetris) mit 582.

Kreisdiagramm

grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(Anzahl =n())

grouped$Anzahl<-as_vector(grouped$Anzahl)
ordered <- grouped[order(grouped$Anzahl), decreasing = FALSE]
ordered$Genre <- as_factor(ordered$Genre)


ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Anzahl"

)

ordered%>%
  plot_ly() %>% 
  add_pie(values =~Anzahl,labels=~Genre,
           name="Videospielanzahl nach Genre"
          ,colors = myPalette) %>% 
  layout(title="Videospielanzahl nach Genre",
         xaxis = ax,
         yaxis = ay
         )

Der Anführer der Liste ist mit deutlichem Abstand Action (GTA,Bloodborne) mit 20%. Auf dem Zweiten platz findet sich Sports (14.1%) mit reihen wie FIFA und NBA2k. Den dritten Platz belegt ein Genre das aus vielen verschiedenen Genren besteht die in dieser Liste nicht aufgeführt werden mit 10.5%. Misc beinhaltet spiele wie Just Dance (Musik/Rhythmus) oder Minecraft ein Sandbox Survival game. Danach kommen mit geringerem Abstand der Reihe nach Role-Playing (Witcher, The Elder Scrolls) mit 8.96%, Shooter (Call of Duty, Doom) mit 7.89%, Adventure (God of War, Life is Strange) mit 7.75% und Racing (Gran Tourismo, Forza) mit 7.53%. Danach folgen mit einem größeren Abstand Platform (Super Mario, LittleBigPlanet) mit 5.34%, Simulation (Sims, Microsoft Flight Simulator) mit 5.22% sowie Fighting (Tekken, Super Smash Bros) mit 5.11%. Zu guter letzt fehlen noch Strategy (Age of Empires, Civilisation) mit 4.1% sowie Puzzle (Portal,Tetris) mit 3.51%.

Auffällig hierbei ist das die Größten vier Genres 53.56% der Spielereleases ausmachen. Dies ist ansich nicht weiter Verwunderlich. In der Spieleindustrie bzw allgemein, ist es ein gerne genutztes konzept Funktionierende dinge zu übernehmen. Dies ist vorallem auffällig bei Spielen, welche ganze Genres prägen. Sei es Minecraft für die Survival Games (DayZ, Rust), World of Warcraft für die MMORPG’s (Final Fantasy 14, Guild Wars 2) oder die Warcraft 3 mod Dota welche das MOBA genre (League of Legends, Dota 2) nach sich gezogen hat.


Genreverteilung der Videospiele nach Verkaufszahlen

Schauen wir uns nun jedoch an ob die Verkaufszahlen die gleichen häufungen aufzeigen und verwenden wieder ein Pareto- und Kreisdiagramm. Es gilt weiterhin die obengenannte Problematik der Genrenotation des Datensatzes.

Verkaufszahlen

Balkendiagramm


grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Verkäufe (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Genre,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="Verkaufszahlen nach Genre"
           ,colors = myPalette) %>% 
  layout(title="Verkaufszahlen nach Genre",
         xaxis = ax,
         yaxis = ay
         )
NA

Auf Platz 1 und 2 der Liste befinden sich weiterhin Action (1.751 mrd) und Spots (1.33 mrd). Platz 3 belegt hier jedoch nicht Misc welches mit 809.96 mio auf platz 6 abgerutscht ist sondern Shooter (1.037 mrd). Platz 4 wird weiterhin von Role-Playing (927.37 mio) belegt. Auch Platform (831.37) verkaufen sich deutlich besser und sichern sich Platz 5. Die restlichen Genres unterscheiden sich Kaum in Anzahl und Verkaufszahlen.

Kreisdiagramm


grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Verkäufe (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Genre,
           name="Verkaufszahlen nach Genre"
          ,colors = myPalette) %>% 
  layout(title="Verkaufszahlen nach Genre",
         xaxis = ax,
         yaxis = ay
        )

Auf Platz 1 und 2 der Liste befinden sich weiterhin Action (19.6%) und Spots (14.9%). Platz 3 belegt hier jedoch nicht Misc welches mit 9.08% auf platz 6 abgerutscht ist sondern Shooter (11.6%). Platz 4 wird weiterhin von Role-Playing (10.4%) belegt. Auch Platform (9.32%) verkaufen sich deutlich besser und sichern sich Platz 5. Die restlichen Genres unterscheiden sich Kaum in Anzahl und Verkaufszahlen.

Beim Betrachten fällt hier auf, dass sich einige Genres deutlich besser verkaufen als andere. Vorallem Shooter und Platform spiele sind hier die Kassenschlager wenn man die Verkaufszahlen mit Anzahl der Spiele vergleicht. Die großen Genres Action und Sports sind jedoch sowohl in verkaufszahlen als auch Anzahl der Spiele unangefochten auf platz 1 und 2.


Regionale Unterschiede der Genres

Nachdem wir vorhin bei den Platformen deutliche Regionale Unterschiede feststellen konnten stellt sich bei den Genres die gleiche Frage und dementsprechend auch wieder der gleiche Lösungsansatz mit Pareto- und Kreisdiagrammen.

Verkäufe pro Genre

Balkendiagramme

Europa


grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(sum(EU_Sales))  %>%
rename(
    Global_Sales = "sum(EU_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Verkäufe (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Genre,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="Verkaufszahlen nach Genre (EU)"
           ,colors = myPalette) %>% 
  layout(title="Verkaufszahlen nach Genre (EU)",
         xaxis = ax,
         yaxis = ay
         )

Europa sieht wie bereits in der Platformanalyse festgestellt dem Globalen Genrevergleich recht ähnlich. Action (525 mio) führt weiterhin vor Sports(376.85 mio) und Shootern (313.27 mio). Auf platz 4 ist dann der erste Unterschied feststellbar. Anstatt Role-Playing (188.06 mio) welches auf Platz 7 abgerutscht ist befindet sich hier Racing (238.39) welche den Platz tauschen. Auch Platz 5 Misc (215.98 mio) und Platz 6 Platform (201.63 mio) sind in Europa vertauscht. Allgemein scheint hier auf den hinteren Genreplätzen eine verschiebung feststellbar zu sein denn obwohl das verhältnis der Genres gleich bleibt sind zusätzlich sowohl Simulation (113.38 mio) und Fighting (101.32 mio) als auch Adventure (63.13 mio) und Puzzle (50.78 mio) vertauscht. Von den hinteren Plätzen bleibt somit einzig Strategy (45.34 mio) auf seinem vorherigen letzten platz.

Nord-Amerika


grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(sum(NA_Sales))  %>%
rename(
    Global_Sales = "sum(NA_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Verkäufe (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Genre,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="Verkaufszahlen nach Genre (NA)"
           ,colors = myPalette) %>% 
  layout(title="Verkaufszahlen nach Genre (NA)",
         xaxis = ax,
         yaxis = ay
         )

Auch in Nord-Amerika ist eine Verschiebung der Genres festzustellen. Die Top 3 sind weiterhin von Action (877.83 mio), Sports (683.35 mio) und Shooter (582.6 mio) belegt. Im gegensatz zu Europa sind hier allerdings nur Platz 4 Platform (447.05 mio), Platz 5 Misc (410.24 mio) sowie Platz 6 Racing (359.42) und Platz 7 Role-Playing (327.28 mio) vertauscht. Platz 8 bis 12 sind wie die globalen Referenzwerte angeordnet der einzige Unterschied zwische Global und Nord-Amerika ist somit die verschiebung von Role-Playing auf Platz 7.

Japan


grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(sum(JP_Sales))  %>%
rename(
    Global_Sales = "sum(JP_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Verkäufe (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Genre,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="Verkaufszahlen nach Genre (JP)" ,colors = myPalette) %>% 
  layout(title="Verkaufszahlen nach Genre (JP)",
         xaxis = ax,
         yaxis = ay
         )
NA

In Japan befindet sich Role-Playing (352.31 mio) mit großem Abstand auf Platz 1 noch vor de sonstigen Platzhirschen Action (159.95 mio) und Sports (135.37 mio). Die ehemalige top 3 Shooter (38.28 mio) fällt in Japan auf den letzten platz ab und wird von Platform (130.77 mio) ersetzt. Misc (107.76 mio) kann sich weiterhin im mittelfeld halten wohingegen Fighting (87.35 mio) und Simulation (63.7 mio) einige Plätze gut machen können und nun auf Platz 6 und 7 vorrücken. Auch Puzzle Games (57.31 mio) erfreuen sich einer höheren beliebtheit als noch Global wohingegen Racing (56.69 mio) einen deutlichen Verlust hinnehmen muss. Adventure (52.07 mio) und Strategy (49.46 mio) bleiben jedoch weiterhin eine der Unbeliebtesten Genres.

Kreisdiagramme

Europa


grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(sum(EU_Sales))  %>%
rename(
    Global_Sales = "sum(EU_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Verkäufe (in mio)"

)


ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Genre,
           name="Verkaufszahlen nach Genre (EU)" ,colors = myPalette) %>% 
  layout(title="Verkaufszahlen nach Genre (EU)",
         xaxis = ax,
         yaxis = ay
        )

Europa sieht wie bereits in der Platformanalyse festgestellt dem Globalen Genrevergleich recht ähnlich. Action (21.6%) führt weiterhin vor Sports(15.5%) und Shootern (12.9%). Auf platz 4 ist dann der erste Unterschied feststellbar. Anstatt Role-Playing (7.73%) welches auf Platz 7 abgerutscht ist befindet sich hier Racing (9.79%) welche den Platz tauschen. Auch Platz 5 Misc (8.87%) und Platz 6 Platform (8.28%) sind in Europa vertauscht. Allgemein scheint hier auf den hinteren Genreplätzen eine verschiebung feststellbar zu sein denn obwohl das verhältnis der Genres gleich bleibt sind zusätzlich sowohl Simulation (4.66%) und Fighting (4.16%) als auch Adventure (2.63%) und Puzzle (2.09%) vertauscht. Von den hinteren Plätzen bleibt somit einzig Strategy (1.86%) auf seinem vorherigen letzten platz.

Nord-Amerika


grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(sum(NA_Sales))  %>%
rename(
    Global_Sales = "sum(NA_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Verkäufe (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Genre,
           name="Verkaufszahlen nach Genre (NA)",colors = myPalette) %>% 
  layout(title="Verkaufszahlen nach Genre (NA)",
         xaxis = ax,
         yaxis = ay
        )

Auch in Nord-Amerika ist eine Verschiebung der Genres festzustellen. Die Top 3 sind weiterhin von Action (20%), Sports (15.6%) und Shooter (13.3%) belegt. Im gegensatz zu Europa sind hier allerdings nur Platz 4 Platform (10.2%), Platz 5 Misc (9.34%) sowie Platz 6 Racing (8.18%) und Platz 7 Role-Playing (7.45%) vertauscht. Platz 8 bis 12 sind wie die globalen Referenzwerte angeordnet der einzige Unterschied zwische Global und Nord-Amerika ist somit die verschiebung von Role-Playing auf Platz 7.

Japan


grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(sum(JP_Sales))  %>%
rename(
    Global_Sales = "sum(JP_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Verkäufe (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Genre,
           name="Verkaufszahlen nach Genre (JP)" ,colors = myPalette) %>% 
  layout(title="Verkaufszahlen nach Genre (JP)",
         xaxis = ax,
         yaxis = ay
        )

In Japan befindet sich Role-Playing (27.3%) mit großem Abstand auf Platz 1 noch vor de sonstigen Platzhirschen Action (12.4%) und Sports (10.5%). Die ehemalige top 3 Shooter (2.97%) fällt in Japan auf den letzten platz ab und wird von Platform (10.1%) ersetzt. Misc (8.35%) kann sich weiterhin im mittelfeld halten wohingegen Fighting (6.77%) und Simulation (4.93%) einige Plätze gut machen können und nun auf Platz 6 und 7 vorrücken. Auch Puzzle Games (4.44%) erfreuen sich einer höheren beliebtheit als noch Global wohingegen Racing (4.39%) einen deutlichen Verlust hinnehmen muss. Adventure (4.03%) und Strategy (3.83%) bleiben jedoch weiterhin eine der Unbeliebtesten Genres.

Zu erkennen ist hier erneut das Amerika und Euopa recht ähnlich interessen haben und nur auf den mittleren und hinteren plätzen unterschiede aufweisen. Nord-Amerika ist als der größte Markt wie zu erwartend am nächsten an den Globalen Referenzdaten wohingegen Japan ein gänzlich anderes Genreshema erkennen lässt. In Japan dominiert Role-Playing welches sich in Europa und Amerika nur auf platz 7 befindet welches durch die Japanische Kultur geprägt auch sinn ergibt.


Genreentwicklung im laufe der Jahre nach anzahl

Nachdem wir uns nun Über die Genreverteilung Global und in den einzelnen Regionen ein Bild gemacht haben wäre es interessant anzuschauen wie sich die Genres im Laufe der Jahre entwickelt haben und ob sich ein Trend bei Gewissen Genres erkennen lässt. Als erstes Betrachten wir reine Anzahl der Spielereleases und später die verkaufszahlen. Hierzu verwenden wir verschiedene Lineplots die sich in der Datenvorbereitung nicht großartig von den Pareto- und Kreisdiagrammen unterscheidet. Die unterschiede in der Diagramm erstellung werde ich jedoch im Folgenden aufzeigen.

Anzahl der Spiele pro Genre pro Jahr

Lines

Die erstellung des Lines Diagrammes ist wohl die simpelste. Wir verwenden unsere vorgefiltertes data.frame filtered und übergeben dies an die plot_ly() funktion. Danach nutzen wir add_lines um ein Liniendiagramm zu erstellen und setzen die Parameter. Der X-Wert ist das Year, der Y-Wert die Anzahl. Als color wählen wir das Genre und unsere Farbtabelle übergeben wir an die funktion via colors=.


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(Anzahl =n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,Anzahl)
ax <- list(
  title = "Jahr"
)

ay <- list(
  title = "Anzahl"

)

filtered %>%
plot_ly() %>% 
  add_lines(x=~Year,
           y=~Anzahl, color=~Genre,colors = myPalette) %>% 
 layout(title="Anzahl der Spielereleases von 1980-2016",
         xaxis = ax,
         yaxis = ay
         )
NA

Im ersten moment ist dieses Diagramm recht unübersichtlich doch bei genaueren Betrachtung kann ein aufmerksamer Betrachter bereits einige Dinge erkennen. Zum einen sehen wir das zwischen 1993 und 2003 tatsächlich Sports das meist verkaufte Genre war bevor es von Action abgelöst wurde. Misc games erfreuten sich zwischen 2005 und 2011 großer beliebtheit bevor diese wieder in der Versenkung verschwanden. Auch Adventure games waren zwischen 2007 und 2010 am beliebtesten.

Filled Lines

Die Erstellung des Filled Lines Diagrammes unterscheides sich etwas von dem einfach Lines-Plot. Anstatt der add_Lines funktion übergeben wir hier direkt die Parameter mit an plot_ly(). X ist weiterhin das Jahr, Y die Anzahl, die Farbtablette colors und color=Genre. Die Unterschiede sind hier der type parameter welcher auf scatter gesetz wird, mode welches none ist und fill welches durch tozeroy die füllung bis zur y Achse erzeugt.


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(Anzahl =n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,Anzahl)
ax <- list(
  title = "Jahr"
)

ay <- list(
  title = "Anzahl"

)


filtered %>%
plot_ly(x = ~Year, y = ~Anzahl, type = 'scatter', mode = 'none', fill = 'tozeroy',color = ~Genre ,colors = myPalette)%>% 
  layout(title="Anzahl der Spielereleases von 1980-2016",
         xaxis = ax,
         yaxis = ay
         )
NA

Einige feinere unterschiede Lassen sich hier deutlich besser erkennen als noch im Lines Diagramm. Man erkennt beispielsweise den großen Wachstum von Strategy games zwischen 1996 und 1998 bevor diese 2000 stark abflachen und nicht mit dem allgemeinen Wachstum der anderen Genres mithalten können. Auch der große Wachstum von Racing games zwischen 200 und 2004 ist gut erkennbar.

Stacked Lines

Da stacked Lines sehr übersichtlich und gut darin sind sich einen Groberen überblick über die Daten zu schaffen sind diese hier als erste Ansicht vorausgewählt. Um die hinzugehörende Texte hundertprozentig verstehen zu können ist es aber hilfreich zuerst den Lines und Filled Lines tab zu studieren.

Die Erstellung des stacked Lines Diagramm ist den Filled Lines sehr ähnlich. Einziger unterschied ist die Abwesenheit des fill parameters und stattdessen die verwendung von stackgroup=‘one’ welches die stacked Lines erzeugt.


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(Anzahl =n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,Anzahl)
ax <- list(
  title = "Jahr"
)

ay <- list(
  title = "Anzahl"

)


filtered %>%
plot_ly(x = ~Year, y = ~Anzahl, type = 'scatter', mode = 'none', stackgroup = 'one',color = ~Genre, colors = myPalette)%>% 
  layout(title="Anzahl der Spielereleases von 1980-2016",
         xaxis = ax,
         yaxis = ay
         )
NA

Leider sind die Farben aufgrund eines Fehlers hier etwas fehlerhaft mehr dazu im Fazit Beim Betrachten des Stacked Line plots sind jedoch trotzdem einige Dinge direkt sehr gut zu erkennen. Man sieht welche Genres ein größeres Wachstum hinlegen als andere. Sowohl Shooter als auch Puzzle und Platform Games bleiben in den 2010er jahren relativ gleichbleibend. Action, Strategz, Misc und Sports Games können jedoch ein deutliches Wachstum aufzeigen.

Genreverschiebung

Schauen wir uns nun die Erstellung der zum vergleichen der Genres wohl interessantesten Grafik an. Die erstellung ist hier quasi gleich zu den Stacked Lines. Einzige neuerung ist das hinzufügen des Parameters groupnorm = ‘percent’ welches die Y-Achse von dem wert der Anzahl zu Prozentwerten ändert. Auch hier sind jedoch die Farben leider Fehlerhaft.


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(Anzahl =n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,Anzahl)
ax <- list(
  title = "Jahr"
)

ay <- list(
  title = "Prozent %"

)


filtered %>%
plot_ly(x = ~Year, y = ~Anzahl, type = 'scatter', mode = 'none', stackgroup = 'one',groupnorm = 'percent',color = ~Genre ,colors = myPalette)%>% 
  layout(title="Marketshare Genreverschiebung in % von 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Beim Betrachten fällt hier direkt auf, dass Action Games 1980-1984 einen großen Marktanteil, teilweise bis hin zu 50% ausgemacht haben. Diese bis 1994 auf gerademal 3% absinken bevor der Stetige Wachstum beginnt bis sie 2016 wieder bei Knap 40% enden. Auch die große Marktpräsenz von Platform Spielen zwischen 1984 und 1992 ist gut erkennbar wohingegen Racing Games sich zwischen 1994 und 2004 der größten beliebtheit erfreuen.

Hierbei zu erkennen ist Obwohl die Anzahl der Jährlichen Spielereleases über die Jahre hinweg stetig wächst bleiben die Meisten Genres ähnlich viel vertreten. Auffällig sind hierbei Strategy-Games die erst 1991 das erste mal auftretem Seitdem obwohl sie Leicht an Marketshare verlieren grob gleich bleiben. Außerdem sind Action Games die Spiele mit der wohl größten volatilität. Sind es 1982 noch fast 50% der Gamereleases fällt deren aufkommen 1084 schon auf nur noch knapp 10% ab und 1986 steigt der Wert wieder auf fast 30%. Dieser Trend setzt sich fort bis 1996 ab welchem Zeitpunkt sich Action Games von 3.6% über die Jahre bis 2016 bis 35% entwickeln.


Genreentwicklung im laufe der Jahre nach Verkaufszahlen

Schauen wir uns an wie sich die verkäufe entwickelt haben. Hierzu verwenden wir die gleichen Diagramme wie bereits bei der Betrachtung der Spiele Anzahl. Eine erklärung der erstellung der Diagramme gibt es hier.

Verkäufe pro Jahr

Lines


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,gr_sum)

ax <- list(
  title = "Jahr"
)

ay <- list(
  title = "Verkäufe (in mio)"

)

filtered %>%
plot_ly() %>% 
  add_lines(x=~Year,
           y=~gr_sum, color=~Genre ,colors = myPalette) %>% 
  layout(title="Verkaufszahlen der Spielereleases von 1980-2016",
         xaxis = ax,
         yaxis = ay
         )
NA

Beim ersten Betrachten fällt hier direkt die hohe volatilität der einzelnen Graphen auf, welches durch den hohen Einfluss einiger gutlaufender Games auf die Verkaufszahlen zurückzuführen ist. Am einfachsten ist dies zwischen 1980 und 1992 erkennbar. 1981 ist ein spike in Action Games erkennbar, nametlich durch die veröffentlichung namentlicher spiele wie Frogger und Pitfall. Im Jahr 1984 erkennbar ist dann der spike von Shootern durch Duck-Game sowie Platform games in 1985 durch Super Mario Bros. Super Mario prägt die Historie der Platform Games auch zwischen 1988 und 1990 mit Super Mario Bros 3 und Super Mario World. Das Spiel welches 1989 einen ausschlag der Puzzle-Games verursacht dürfte sogar Lesern, welche nicht Teil der Gaming-Community sind ein begriff sein: Tetris.

Filled Lines


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,gr_sum)

ax <- list(
  title = "Jahr"
)

ay <- list(
  title = "Verkäufe (in mio)"

)


filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', fill = 'tozeroy',color = ~Genre ,colors = myPalette) %>% 
  layout(title="Verkaufszahlen der Spielereleases von 1980-2016",
         xaxis = ax,
         yaxis = ay
         )
NA

Durch Betrachten des Filled Line Plots erkennen wir gut den Hoch der Strategiespiele im Jahr 1999 durch spiele wie Pokemon Stadium, Warzone 2100 oder Age of Empires II. Auch die Spikes der Role-Playing Games im gleichen Jahr durch Pokemon Gold/Silber und Final Fantasy VIII sowie 1996 durch Pokemon Rot/Blau sind deutlich erkennbar.

Stacked Lines


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,gr_sum)

ax <- list(
  title = "Jahr"
)

ay <- list(
  title = "Verkäufe (in mio)"

)


filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', stackgroup = 'one',color = ~Genre ,colors = myPalette)%>% 
  layout(title="Verkaufszahlen der Spielereleases von 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Stacked Lines sind vermutlich das Beste Diagramm um Verkaufszahlen mit der Anzahl zu vergleichen. Am auffälligsten hier sind, dass die Volatilität in den früheren Jahren (1980-1995) bei geringerer präsenz von Videospielen deutlich größer ausfällt als in der anzahl der Videospiele. In den Späteren Jahren vorallem ab 2003 fallen die Schwankungen hier jedoch deutlich geringer aus, was vermutlich an der höheren Masse von Videospielen und damit einem breit gefächerterem Nutzerinteresse liegt.

Genreverschiebung


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,gr_sum)

ax <- list(
  title = "Jahr"
)

ay <- list(
  title = "Prozent %"

)


filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', stackgroup = 'one',groupnorm = 'percent',color = ~Genre ,colors = myPalette)%>% 
  layout(title="Marketshare Genreverschiebung in % von 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Durch die hohe Volatilität ist die Grafik in den früheren Jahren vorallem zwischen 1980 und 1992 sehr durcheinandern und Teilweise recht schwierig zu lesen. In den darauf folgenden Jahren ist es aber deutlich leichter bestimmte dinge wie das erstmalige auftretens der Strategiespiele 1992 oder die fast Vollständige Abstinenz von Puzzle Games zwischen 1995 und 2002 sowie ab 2012 zu erkennen.

Wie zu erwarten lässt sich hier ein Großer overlap zu den Anzahl der Gamereleases feststellen es kann jedoch eine Hohe Volitilität durch einzelne Spielereleases vorallem in früheren Jahren festgestellt werden. Dies hat den Grund das einige “Kassenschlager” hier einen großteil des Marktes ausmachen und ihn somit stark beeinflussen. Anzumerkten ist jedoch das Spiele gerne Rereleast werden vorallem auf unterschiedlichen Konsolen, dies in unserem Datensatz jedoch nicht zusammegeführt wird. Weiteres hierzu im Fazit


Genreentwicklung im laufe der Jahre nach Verkaufszahlen pro Spiel

Nachdem wir nun Analysiert haben wie sich die Anzahl der Spielereleases sowie die Verkaufszahlen entwickelt haben wäre es doch interessant beides gegenüberzustellen und direkt zu vergleichen. Hierzu verwenden wir erneut die bereits bekannten Diagramme nutzen jedoch in der dplyr::summarize() funktion die Summe der Verkaufszahlen welche wir durch die Anzahl der Einträge teilen.

Verkäufe pro Spiel pro Jahr

Lines


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)/n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,gr_sum)
ax <- list(
  title = "Jahr"
)

ay <- list(
  title = "Verkäufe pro Spiel"

)

filtered %>%
plot_ly() %>% 
  add_lines(x=~Year,
           y=~gr_sum, color=~Genre ,colors = myPalette) %>% 
  layout(title="Verkäufe pro Spiel nach Genre von 1980-2016",
         xaxis = ax,
         yaxis = ay
         )
NA

Im Lines-Plot erkennen wir direkt die in der Verkaufszahlanalys genannten Extreme welche durch einzelne Spiele, vorallem in den früheren Jahren, beeinflusst werden. Am deutlichsten ist dies in Shooter Games 1984 durch Duck-Game und Platform spiele 1985 durch Super Mario Bros. Auch Tetris (Puzzle 1989) sowie Super Mario Bros 3 (Platform 1988) und Super Mario World (Platform 1990) sind deutlich erkennbar. Neu erkennbar ist hier der Ausschlag in Racing games 1992 durch den Klassiker Super Mario Kart wessen Nachfolger bis heute auf fast jeder Nintendo Konsole veröffentlicht wurden.

Filled Lines

In dem Fall der Verkäufe Pro Jahr sind die Stacked Lines leider wenig ausschlaggebend und daher auch nicht als erste ansicht vorausgewählt. Zum verstehen der Analyse sollte jedoch der Lines-Tab zuerst gelesen werden.


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)/n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,gr_sum)
ax <- list(
  title = "Jahr"
)

ay <- list(
  title = "Verkäufe pro Spiel"

)

filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', fill = 'tozeroy',color = ~Genre ,colors = myPalette) %>% 
  layout(title="Verkäufe pro Spiel nach Genre von 1980-2016",
         xaxis = ax,
         yaxis = ay
         )
NA

Beim Betrachten der Filled-Lines fällt auf das neben den Bereits genannten Extremen Racing games auch im Jahre 1990 schon einen Hochpunkt durch F-1 Race erfuhr. Auch das Extrem des Action genres 1987 durch Zelda II: The Adventure of Link ist hier deutlicher erkennbar.

Stacked Lines


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)/n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,gr_sum)
ax <- list(
  title = "Jahr"
)

ay <- list(
  title = "Verkäufe pro Spiel"

)

filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', stackgroup = 'one',color = ~Genre, colors = myPalette)%>% 
  layout(title="Verkäufe pro Spiel nach Genre von 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Stacked Lines ist hier für eine Analyse der einzelnen Spielegenres leider nicht hilfreich. Der aufmerksame Beobachter wird sich jedoch an eine der ersten Grafiken erinnern in denen wir die Sales pro Game analysiert haben und sich Fragen warum die Werte hier deutlich höher ausfallen als noch bevor. War in der Analyse ohne Genres der Maximalwert noch bei 4 so ist er Hier bei mehr als 20. Dies liegt vorallem daran, dass Action games in den Früheren Jahren einen großteil der Releases ausmachen bei den verkaufszahlen aber eher gering ausfallen und den durchschnitt daher herunterziehen. Sind die Spiele nach Genre aufgeteilt beeinflusst das schlecht performende Action Genre die Verkaufszahlen pro Spiel der anderen jedoch nicht und so erhalten wir additiv eine deutlich größere Zahl als zuvor.

Genreverschiebung


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)/n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,gr_sum)
ax <- list(
  title = "Jahr"
)

ay <- list(
  title = "Prozent %"

)
filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', stackgroup = 'one',groupnorm = 'percent',color = ~Genre, colors = myPalette)%>% 
  layout(title="Marketshare in Verkäufe pro Spiel nach Genre von 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Durch die hohe volatilität in den Früheren Jahren ist auch hier wie bei den Verkaufszahlen das Genreshift Diagramm wenig ausschlaggebend. AB 1994 kann man jedoch deutlich erkennen wir sich die Genres im laufe der Jahre entwickeln. Shooter werden deutlich beliebter wohingegebn Role-Playing games auf dem absteigenden Ast sind.

Auch hier ist wie erwartet die Entwicklung Prozentual ähnlich. Auffällig ist jedoch das Shooter trotz ihrer geringen Vertretung in der Prozentualen Verteilung 1984 sowie 2014,2015 und 2016 die Nase Vorne haben. Platform Games haben 1985,1988 und 1990 die Nase Vorne. Die Hochzeit der Puzzle Games sind unangefochten 1988 mit dem Weltweitbekannten und auf Platz 6 der meistverkauften videospiele: Tetris. Auffällig sind vorallem die Moderneren entwicklungen. Sind in den 1996-2005er Jahren Role-Playing und somit langsame immersive erlebnisse noch deutlich Beliebter haben heutzutage Shooter mit ihrem Rundenbasiertem, “Fast Paced” also schnellem spielfluss die Nase Vorne. In der Modernen Welt ist es deutlich einfacher und für Viele leute weniger Zeitintensiv kurz eine Runde von 15-45 minuten zu spielen als sich Stundenlang in eine Rolle hineinzuversetzen. Vielen Menschen fehlt einfach Zeit oder Geduld um sich in der Zeit von modernen Medien wie Tik-Tok oder Instagramm, welche sich auf kurze erlebnisse von oft wenigen Sekunden spezialisiert haben, in ein Immersives erlebnis hereinzuversetzen.


Genreverteilung nach Publisher

Da wir nun sowohl Genres als auch Publisher betrachtet haben wäre es doch der einzig logische schritt diese beiden Daten zusammenzuführen und zu vergleichen. Gibt es hier Publisher die verschiedene Genres bevorzugen bzw. deren Bestseller sich in bestimmten Genres Tummeln?

Hierzu verwenden wir ein stacked Bar-Plot. Der beginn der Diagrammerstellung ist hierbei ähnlich wie noch bei Paretodiagrammen. Relativ schnell fällt hier jedoch auf das wir anstatt nur eines Dataframes Zwei Produzieren. Zum einen der bereits bekannte grouped Dataframe welcher Publisher, Genre und Verkaufszahlen ebenjener Genres beinhaltet. Zum anderen PublisherSales welcher eine Liste der Publisher mit Gesamtverkaufszahlen von mehr als 300 mio enthält. Diesen verwenden wir im weiteren verlauf um aus unserem grouped Datensatz alle Publisher zu entfernen die sich nicht in PublisherSales befinden. Das geschieht mit hilfe des filter() commands und dem Schlagwort %in%. Der rest der Diagrammerstellung verhält sich equivalent zur Publisheranalyse mit dem unterschied das die Bars bei der Diagrammerstellung nicht sortiert werden.

Genreverteilung pro Publisher

Verkäufe



grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) 
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
PublisherSales <- grouped %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)

grouped <- grouped %>% filter(Publisher %in% PublisherSales$Publisher)

grouped$Global_Sales<-as_vector(grouped$Global_Sales)

grouped$Publisher <-str_remove_all(grouped$Publisher, "Entertainment")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Interactive")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Studios")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Games")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Game")

  

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Verkäufe (in mio)"

)

grouped%>%
  plot_ly(x=~Publisher,
           y=~Global_Sales,
            type='bar',
           color=~Genre, colors = myPalette)  %>% 
  layout(title="Verkäufe pro Genre pro Publisher",
         xaxis = ax,
         yaxis = ay,
         barmode = 'stack'
         )
NA
NA

Beim Betrachten der Verkaufszahlen fällt direkt auf, dass die meisten Publisher bestimmte Genres präferieren. Activision haben mit Call of Duty einen großteil ihrer verkäufe im Shooter Genre. Das Electronic Arts mit FIFA und MaddenNFL im Sport Genre breit vertreten sind ist wenig Verwunderlich. Shootern (Battlefield) und Racing (Need for Speed) sind jedoch auch sehr Beliebte Genres bei dem US-basiertem Gaming riesen. Nintendo spezifiziert sich wenig Verwunderlich auf Platform (Super Mario) und Role-Playing(Pokemon). Sony hingegen fächern ihr angebot relativ breit und haben neben 110.57 mio in Racing auch 104 mio in Platform, 80 mio in Misc und 94.5 mio in Action. Take-Two mit Grand Theft Auto und Read dead Redemption spezifieren sich wenig verwunderlich auf Action wohingegen sich THQ wieder relativ breit fächert. Zu guter letzt fährt Ubisoft eine zweigeteilte Schniene mit Action (Assassin’s Creed) und Misc (Just Dance).

Anzahl




grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(Anzahl =n(),sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    )
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
PublisherSales <- grouped %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)

grouped$Global_Sales<-as_vector(grouped$Global_Sales)
grouped$Publisher <-str_remove_all(grouped$Publisher, "Entertainment")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Interactive")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Studios")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Games")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Game")



ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Anzahl"

)

grouped%>%
  plot_ly(x=~Publisher,
           y=~Anzahl,
            type='bar',
           color=~Genre ,colors = myPalette)  %>% 
  layout(title="Anzahl pro Genre pro Publisher",
         xaxis = ax,
         yaxis = ay,
         barmode = 'stack'
         )
NA
NA
NA

Betrachten wir die Anzahl der Spiele und stell diese den Verkaufszahlen gegenüber fällt hier vorallem auf, dass Firmen mit Focus in den Verkaufszahlen diese in der Produktion noch mehr Prioritisieren. Interessant ist auch, das Activison produktionsfocus deutlich mehr auf action Games liegt als auf Shootern diese sich im vergleich jedoch deutlich schlechter verkaufen.

Bei dem vergleich der Werte ist hier zu bemerken, dass die meisten Publisher Hierbei sich mit der Anzahl der Spiele und den Sales gut abdecken. Die auffälligsten diskrepanzen sind hierbei EA mit dem Sports Genre und ihren järlich releasten Spielen FiFa/NBA2k etc. sowie Nintendo mit der Platformreihe Super Mario.


Genreverteilung für Publisher Electronic Arts

Schauen wir uns diese Beiden Firmen noch einmal im Detail an. Hierzu verwenden wir erneut Pareto- und Kreisdiagramm die uns bereits aus vorderen Teilen der Ausarbeitung bekannt sind.

Genre für Electronic Arts

Balkendiagramme

Verkaufszahlen



grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% 
  filter(Publisher == "Electronic Arts")
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
grouped$Global_Sales<-as_vector(grouped$Global_Sales)

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Verkäufe (in mio)"

)

grouped%>%
  plot_ly() %>% add_bars(x=~Genre,
           y=~Global_Sales,
           color=~Genre ,colors = myPalette)  %>% 
  layout(title="Verkaufszahlen für Electronic Arts",
         xaxis = ax,
         yaxis = ay,
         barmode = 'stack',
         showlegend = FALSE
         )
NA

Beim Betrachten der Sales erkennen wir das wie bereits vorher festgestellt Sports (479.67 mio) an erster Stelle steht. Mit deutlichem Abstand danach folgen Shooter (158.26 mio), Racing (145.77 mio) und Action (115.54 mio). Das einzig andere Relevante Genre ist Simulation mit 89.53 mio in Sales. Role-Playing (35.3 mio), Fighting (31.39 mio), Misc (24.95 mio) sowie Strategy (14.08 mio), Platform (6.53 mio), Adventure (4.75 mio) und Puzzle (4.55 mio) spielen eine eher untergeordnete Rolle.

Anzahl


grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(Anzahl =n())  %>% 
  filter(Publisher == "Electronic Arts")
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Anzahl"

)


grouped%>%
  plot_ly() %>% add_bars(x=~Genre,
           y=~Anzahl,
           color=~Genre ,colors = myPalette)  %>% 
  layout(title="Anzahl der Spielereleases nach Genre für Electronic Arts ",
         xaxis = ax,
         yaxis = ay,
         barmode = 'stack',
         showlegend = FALSE
         )
NA

In der Detaillansicht sehen Anzahl der Spiele und Sales deutlich geringer aus. Den ersten Platz belegt weiterhin Sports (561) vor Action (183), Racing (159), Shooter (139) und Simulation (116). Auch die eher irelevanten Genres wie Misc (46), Fighting (39) und Strategy (37) sind weiterhin kaum vertreten.

Kreisdiagramme

Verkaufszahlen



grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% 
  filter(Publisher == "Electronic Arts")
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
grouped$Global_Sales<-as_vector(grouped$Global_Sales)

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Verkäufe (in mio)"

)

grouped%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Genre,textinfo='label+percent', rotation = 110, sort = FALSE,
           name="Verkaufszahlen pro Genre für Electronic Arts" ,colors = myPalette) %>% 
  layout(title="Verkaufszahlen pro Genre für Electronic Arts",
         xaxis = ax,
         yaxis = ay,
         showlegend = FALSE,
         autosize = F
         )
NA
NA

Beim Betrachten der Sales erkennen wir das wie bereits vorher festgestellt Sports (43.2%) an erster Stelle steht. Mit deutlichem Abstand danach folgen Shooter (14.3%), Racing (13.1%) und Action (10.4%). Das einzig andere Relevante Genre ist Simulation mit 8.06% der Sales. Role-Playing (3.18%), Fighting (2.83%), Misc (2.25%) sowie Strategy (1.27%), Platform (0.588%), Adventure (0.428%) und Puzzle (0.41%) spielen eine eher untergeordnete Rolle.

Amnzahl


grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(Anzahl =n())  %>% 
  filter(Publisher == "Electronic Arts")
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Anzahl"

)

grouped%>%
  plot_ly() %>% 
  add_pie(values =~Anzahl,labels=~Genre,textinfo='label+percent',sort = TRUE, rotation = 90,
           name="Anzahl der Spielereleases pro Genre für Electronic Arts" ,colors = myPalette) %>% 
  layout(title="Anzahl der Spielereleases pro Genre für Electronic Arts",
         xaxis = ax,
         yaxis = ay,
         showlegend = FALSE,
         autosize = F
         )
NA

In der Detaillansicht sehen Anzahl der Spiele und Sales deutlich geringer aus. Den ersten Platz belegt weiterhin Sports (41.5%) vor Action (13.5%), Racing (11.8%), Shooter (10.3%) und Simulation (8.59%). Auch die eher irelevanten Genres wie Misc (3.4%), Fighting (2.89%) und Strategy (2.74%) sind weiterhin kaum vertreten.

Schauen wir uns EA hier im Detail an fällt auf das die Diskrepanz zwischen Sales und Anzahl der Gamereleases für EA bei Sports gar nicht so groß ist (41.5% vs 43.2%) wie vorher gedacht. Die größeren diskrepanzen sind hier Shooter welches nur 10% der Gamereleases sind aber gut 15% der Sales und Action mit 13.5% der Gamereleases und 10.4% der Sales.

Genreverteilung für Nintendo

Nachdem wir nun herausgefunden haben das bei Electronic Arts die Diskrepanz zwischen Sales und Anzahl der Spiele gar nicht so groß ist wie vorher gedacht betrachten wir nun die gleichen Daten für Nintendo. Die Frage die sich hier stellt ist ob bei Nintendo ein ähnlicher verlauf feststellbar ist oder ob sich bei diesen bestimmte Genres einfach deutlich besser verkaufen als sie sollten.


Genreverteilung für Nintendo

Balkendiagramme

Verkaufszahlen



grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% 
  filter(Publisher == "Nintendo")
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
grouped$Global_Sales<-as_vector(grouped$Global_Sales)

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Verkäufe (in mio)"

)

grouped%>%
  plot_ly() %>% add_bars(x=~Genre,
           y=~Global_Sales,
           color=~Genre ,colors = myPalette)  %>% 
  layout(title="Verkaufszahlen pro Genre für Nintendo",
         xaxis = ax,
         yaxis = ay,
         barmode = 'stack',
         showlegend = FALSE
         )
NA
NA

Wie bereits in der Genreanalyse der Publisher festgestellt verkaufen sich Platform-Spiele (427.21 mio) für Nintendo am besten. Doch auch Role-Playing (284.9 mio), Sports (218 mio) und Misc (180.67 mio) machen keinen unwesentlichen Teil ihrer Verkäufe aus. Selbst die weniger Prominenten Genres wie Racing (151.3 mio), Action (128.18 mio) und Puzzle (124.88 mio). verkaufen sich immernoch deutlich besser als die entsprechenden Spielegenres der Konkurrenz EA. Am deutlichsten ist der Unterschied vermutlich bei den ganz “kleinen” Genres Simulation (85.27 mio), Shooter (69.73 mio), Fighting (53.35 mio) und Adventure (35.71). Auch wenn diese sich nicht an der Exakt gleichen stelle in der Rangliste der Sales befinden hat der letzte Platz von Nintendo Strategy (27.35%) dennoch mehr als das 6 Fache an Sales als der von EA. Trotz das Nintendo mehr Total Sales hat als Electronic Arts ist dieser wert nicht 6 mal so groß sondern umfasst nichtmal das doppelte.

Anzahl


grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(Anzahl =n())  %>% 
  filter(Publisher == "Nintendo")
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Anzahl"

)



grouped%>%
  plot_ly() %>% add_bars(x=~Genre,
           y=~Anzahl,
           color=~Genre ,colors = myPalette)  %>% 
  layout(title="Anzahl der Spielereleases nach Genre für Nintendo",
         xaxis = ax,
         yaxis = ay,
         barmode = 'stack',
         showlegend = FALSE
         )
NA

Im ersten Moment fällt direkt auf, dass der Ausschlag von Platform (112) hier deutlich geringer ausfällt als noch in den Verkaufszahlen. Sowohl Role-Playing (106) als auch Misc (100) umfassen nur ein paar weniger Spiele. Auch das Mittelfeld umfasst mit Action (79), Puzzle (74) und Sports (55) immernoch eine Relativ große Anzahl an Spielen. Selbst die hinteren Plätze mit Racing (37), Adventure (35) und Strategy (32) sind nur knapp vor Simulation (29), Shooter (26) und Fighting (18).

Kreisdiagramme

Verkaufszahlen



grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% 
  filter(Publisher == "Nintendo")
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
grouped$Global_Sales<-as_vector(grouped$Global_Sales)

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Verkäufe (in mio)"

)

grouped%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Genre,textinfo='label+percent',sort = TRUE,
           name="Verkäufe nach Genre für Nintendo" ,colors = myPalette) %>% 
  layout(title="Verkäufe nach Genre für Nintendo",
         xaxis = ax,
         yaxis = ay,
         showlegend = FALSE,
         autosize = F
         )
NA
NA

Wie bereits in der Genreanalyse der Publisher festgestellt verkaufen sich Platform-Spiele (23.9%) für Nintendo am besten. Doch auch Role-Playing (15.9%), Sports (12.2%) und Misc (10.1%) machen keinen unwesentlichen Teil ihrer Verkäufe aus. Selbst die weniger Prominenten Genres wie Racing (8.47%), Action (7.17%) und Puzzle (6.99%). verkaufen sich immernoch deutlich besser als die entsprechenden Spielegenres der Konkurrenz EA. Am deutlichsten ist der Unterschied vermutlich bei den ganz “kleinen” Genres Simulation (4.77%), Shooter (3.9%), Fighting (2.99%) und Adventure (2%). Auch wenn diese sich nicht an der Exakt gleichen stelle in der Rangliste der Sales befinden hat der letzte Platz von Nintendo Strategy (1.53%) dennoch mehr als das 6 Fache an Sales als der von EA. Trotz das Nintendo mehr Total Sales hat als Electronic Arts ist dieser wert nicht 6 mal so groß sondern umfasst nichtmal das doppelte.

Anzahl


grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(Anzahl =n())  %>% 
  filter(Publisher == "Nintendo")
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Anzahl"

)

grouped%>%
  plot_ly() %>% 
  add_pie(values =~Anzahl,labels=~Genre,textinfo='label+percent',sort = TRUE,
           name="Anzahl nach Genre für Nintendo" ,colors = myPalette) %>% 
  layout(title="Anzahl nach Genre für Nintendo",
         xaxis = ax,
         yaxis = ay,
         showlegend = FALSE
         )
NA

Im ersten Moment fällt direkt auf, dass der Ausschlag von Platform (15.9%) hier deutlich geringer ausfällt als noch in den Verkaufszahlen. Sowohl Role-Playing (15.1%) als auch Misc (14.1%) umfassen nur ein paar weniger Spiele. Auch das Mittelfeld umfasst mit Action (11.2%), Puzzle (10.5%) und Sports (7.82%) immernoch eine Relativ große Anzahl an Spielen. Selbst die hinteren Plätze mit Racing (5.26%), Adventure (4.98%) und Strategy (4.55%) sind nur knapp vor Simulation (4.13%), Shooter (3.7%) und Fighting (2.56%).

Beim vergleichen der Werte von Nintendo wird einem aufmerksamen beobachter ziemlich schnell klar, dass Platform Spiele ein Kassenchlager sind. Nehmen diese nur 16% der spielereleases ein so bringen sie dennoch 24% der Sales ein. Gleiches Gilt für Sport games. 8% gegenüber 12%. Action (11% vs 7%), Misc (14% vs 10%) und Puzzle Games (10.5% vs 7%) sind jedoch nicht so erfolgreich. Die Frage woran dies liegen könnte wäre bestimmt auch eine interessante und etwas für einen Ausblick in die Zukunft


Ausblick in die Zukunft

Bei der Analyse des Datensatzes beziehungsweise der Entstandenen Grafiken sind sowohl dem Aufmerksamen leser als auch mir dem Ersteller einige weiter Ideen beziehungsweise weitere Ansätze gekommen die mit sicherheit interessant wären zu Verfolge. Einige dieser Beispiele habe ich im Folgenden als Ideen für Zukünftige Projekte Niedergeschrieben.

Dies ist nur ein kleiner ausschnitt der schier unendlichen Möglichkeiten die einem bei der Analyse von den mittlerweile mehr als 4 mio Videospielen bleibt und das nur angenommen wir bleiben bei einem eher allgemeinerem Vergleich. Jedes dieser Videospiele hat vermutlich genug öffentliche Daten um eine Arbeit zu produzieren die ein vielfaches des Volumens dieser Arbeit, für welche mir nur knapp 70h zu Verfügung standen, hat.

Aufgetretene Probleme

Nun aber zu dem unschönen teil einer jeder Arbeit. Den aufgetretenen Problemen, welche entweder nicht lösbar oder eine relativ starke überarbeitung der Ausarbeitung nachziehen würden.

Literatur und Quellenverzeichnis

LS0tDQp0aXRsZTogIlZpZGVvc3BpZWwgVmVya8OkdWZlIg0Kb3V0cHV0OiANCiAgIA0KICAgaHRtbF9kb2N1bWVudCA6IA0KICAgICAgaW5jbHVkZXM6DQogICAgICAgIGFmdGVyX2JvZHk6IGZvb3Rlci5odG1sDQogICAgICB0aGVtZTogY29zbW8NCiAgICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgaHRtbF9ub3RlYm9vayA6IA0KICAgICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgICBpbmNsdWRlczoNCiAgICAgICAgYWZ0ZXJfYm9keTogZm9vdGVyLmh0bWwNCiAgICAgIHRoZW1lOiBjb3Ntbw0KLS0tDQo8Y2VudGVyPiFbXShWaWRlb2dhbWVzLnBuZykgPC9jZW50ZXI+DQo8Y2VudGVyPiANCiMgRmxvcmlhbiBSZWljaGxlIA0KPC9jZW50ZXI+DQoqKioNCg0KIyMjICoqQW5nYWJlbiB6dSBkZW4gRGF0ZW4qKg0KRGFzIHZlcndlbmRldGUgRGF0YXNldCBkZXMgUHJvamVrdHM6IGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vZGF0YXNldHMvZ3JlZ29ydXQvdmlkZW9nYW1lc2FsZXMgICANCkRpZXMgYmVzdGVodCBhdXMgZGVuIERhdGVuIHZvbiBodHRwczovL3d3dy52Z2NoYXJ0ei5jb20vIGbDvHIgZGllIEphaHJlIDE5ODAgYmlzIDIwMTYgdW5kIHVtZmFzc3QgZGllIEZvbGdlbmRlbiBTcGFsdGVuIGJ6dy5EYXRlbi4NCg0KKiBSYW5rIC0gRGllIFBsYXR6aWVydW5nIGRlcyBTcGllbHMgbmFjaCBBbnphaGwgZGVyIFZlcmvDpHVmZW4NCiogTmFtZSAtIERlciBOYW1lIGRlcyBTcGllbHMNCiogUGxhdGZvcm0gLSBEaWUgUGxhdGZvcm0gYXVmIGRlciBkYXMgU3BpZWwgdmVyw7ZmZmVudGxpY2h0IHd1cmRlICh6LkIuIFBDLFBTNCwgZXRjLikNCiogWWVhciAtIERhcyBKYWhyIGRlciBWZXLDtmZmZW50bGljaHVuZyBkZXMgU3BpZWxzDQoqIEdlbnJlIC0gRGFzIEdlbnJlIGRlcyBTcGllbHMgKHouQi4gU3BvcnQsQWN0aW9uLCBQdXp6bGUpDQoqIFB1Ymxpc2hlciAtIERlciBQdWJsaXNoZXIgZGVzIFNwaWVscw0KKiBOQV9TYWxlcyAtIERpZSBBbnphaGwgZGVyIFZlcmvDpHVmZSBpbiBOb3JkLUFtZXJpa2EgKGluIG1pbGxpb25lbikNCiogRVVfU2FsZXMgLSBEaWUgQW56YWhsIGRlciBWZXJrw6R1ZmUgaW4gRXVyb3BhIChpbiBtaWxsaW9uZW4pDQoqIEpQX1NhbGVzIC0gRGllIEFuemFobCBkZXIgVmVya8OkdWZlIGluIEphcGFuIChpbiBtaWxsaW9uZW4pDQoqIE90aGVyX1NhbGVzIC0gRGllIEFuemFobCBkZXIgVmVya8OkdWZlIGltIFJlc3QgZGVyIFdlbHQgKGluIG1pbGxpb25lbikNCiogR2xvYmFsX1NhbGVzIC0gRGllIEFuemFobCBkZXIgVmVya8OkdWZlIFdlbHR3ZWl0IChpbiBtaWxsaW9uZW4pDQoNCioqKg0KDQojIyMgKipJbmhhbHRzdmVyemVpY2huaXMqKg0KDQoNCjEuIFJlbGVhc2VhbmFseXNlDQogICAgKyBbbmFjaCBBbnphaGxdKCNWaWRlb0dhbWVSZWxlYXNlcykNCiAgICArIFtuYWNoIFNhbGVzXSgjVmlkZW9HYW1lUmVsZWFzZXMpDQogICAgKyBbbmFjaCBTYWxlcyBwcm8gR2FtZV0oI1ZpZGVvR2FtZVJlbGVhc2VzKQ0KICAgIA0KMi4gUGxhdGZvcm1hbmFseXNlDQogICAgKyBbR2xvYmFsXSgjUGxhdGZvcm1hbmFseXNlKQ0KICAgICsgW25hY2ggUmVnaW9uXSgjUGxhdGZvcm1SYW5raW5nQnlSZWdpb24pDQogICAgKyBbVmVya2F1ZnN6aGxlbnR3aWNrbHVuZyBpbSBsYXVmZSBkZXIgSmFocmVdKCNTYWxlc1BlclBsYXRmb3JtKQ0KICAgIA0KMy4gUHVibGlzaGVyYW5hbHlzZSANCiAgICArIFtHbG9iYWxdKCNQdWJsaXNoZXJSZWxlYXNlcykNCiAgICArIFtuYWNoIFJlZ2lvbl0oI1B1Ymxpc2hlclJhbmtpbmdieVJlZ2lvbikNCiAgICANCjQuIEdlbnJlYW5hbHlzZQ0KICAgICsgW25hY2ggQW56YWhsXSgjR2VucmVBbW91bnRHbG9iYWwpDQogICAgKyBbbmFjaCBWZXJrYXVmc3phaGxlbl0oI0dlbnJlU2FsZXNHbG9iYWwpDQogICAgKyBbbmFjaCBSZWdpb25dKCNHZW5yZUFtb3VudEJ5UmVnaW9uKQ0KICAgIA0KNS4gR2VucmV2ZXJ0ZWlsdW5nIHBybyBKYWhyDQogICAgKyBbbmFjaCBBbnphaGxdKCNHZW5yZUFtb3VudFBlclllYXIpDQogICAgKyBbbmFjaCBWZXJrYXVmc3phaGxlbl0oI0dlbnJlU2FsZXNQZXJZZWFyKQ0KICAgICsgW25hY2ggVmVya2F1ZnN6YWhsZW4gcHJvIFNwaWVsXSgjR2VucmVTYWxlc1BlckdhbWVQZXJZZWFyKQ0KICAgIA0KNi4gUHVibGlzaGVyIEdlbnJlcw0KICAgICsgW2bDvHIgZGllIFRvcCBQdWJsaXNoZXJdKCNHZW5yZUJ5UHVibGlzaGVyR2xvYmFsKQ0KICAgICsgW0RldGFpbGFuYWx5c2UgRWxlY3Ryb25pYyBBcnRzXSgjR2VucmVCeVB1Ymxpc2hlckVBKQ0KICAgICsgW0RldGFpbGFuYWx5c2UgTmludGVuZG9dKCNHZW5yZUJ5UHVibGlzaGVyTmludGVuZG8pDQogICAgDQo3LiBLcml0aXNjaGVyIFLDvGNrYmxpY2sNCiAgICArIFtBdXNibGljayBpbiBkaWUgWnVrdW5mdF0oI0F1c2JsaWNrSW5EaWVadWt1bmZ0KQ0KICAgICsgW0F1ZmdldHJldGVuZSBQcm9ibGVtZV0oI0F1ZmdldHJldGVuZVByb2JsZW1lKQ0KICAgICsgW0xpdGVyYXR1cnZlcnplaWNobmlzXSgjTGl0ZXJhdHVydmVyemVpY2huaXMpDQoNCioqKg0KIyMjIFRoZXNlbg0KDQpCZXZvciB3aXIgbWl0IGRlciBBbmFseXNlIGRlciBEYXRlbiBiZWdpbm5lbiBrw7ZubmVuIFN0ZWxsZW4gd2lyIGVyc3RtYWwgZWluIHBhYXIgVGhlc2VuIGJ6dy4gRnJhZ2VzdGVsbHVuZ2VuIGF1ZiBkaWUgd2lyIGltIGxhdWZlIGRlcyBQcm9qZWt0cyBoaW50ZXJmcmFnZW4gYnp3IGJlYW50d29ydGVuIHdvbGxlbi4gIA0KDQoqIFdlbGNoZSBKYWhyZSBzaW5kIGRpZSBiZXN0ZW4gaW4gZGVyIEFuemFobCBkZXIgcmVsZWFzdGVuIEdhbWVzIHVuZCBTYWxlcz8gIFtBbnR3b3J0XSgjVmlkZW9HYW1lUmVsZWFzZXMpDQoqIFdlcmRlbiBoZXV0enV0YWdlIG1laHIgU3BpZWxlIFJlbGVhc3QgdW5kIFZlcmthdWZ0IGFscyBub2NoIDE5ODA/IFtBbnR3b3J0XSgjVmlkZW9HYW1lUmVsZWFzZXMpDQoqIFdlbGNoZSBKYWhyZSBzaW5kIGRpZSBiZXN0ZW4gaW4gQW56YWhsIFNhbGVzIHBybyBHYW1lPyBXZXJkZW4gbmV1ZXJlIFNwaWVsZSBhdXRvbWF0aXNjaCBtZWhyIEdla2F1ZnQ/IFtBbnR3b3J0XSgjVmlkZW9HYW1lUmVsZWFzZXMpDQoNCiogV2VsY2hlIFBsYXR0Zm9ybSBpc3QgZGllIGJlc3RlIGluIEFuemFobCB2ZXJrw6R1ZmVuPyBXZWxjaGUgaW4gQW56YWhsIGRlciBHYW1lIFJlbGVhc2VzPyBbQW50d29ydF0oI1BsYXRmb3JtYW5hbHlzZSkNCiogSGFiZW4gw4RsdGVyZSBQbGF0Zm9ybWVuIEF1dG9tYXRpc2NoIG1laHIgU3BpZWxlIHVuZCBWZXJrw6R1ZmU/IFtBbnR3b3J0XSgjUGxhdGZvcm1SYW5raW5nR2xvYmFsX0VuZCkNCiogRmF2b3Jpc2llcmVuIHZlcnNjaGllZGVuZSBSZWdpb25lbiB2ZXJzY2hpZWRlbmUgUGxhdGZvcm1lbj8gVmVya2F1ZmVuIGRpZSBSZWdpb25lbmhlaW1pc2NoZW4gUGxhdGZvcm1lbiBhdXRvbWF0aXNjaCBhdWNoIGRpZSBtZWlzdGVuIFNwaWVsZT8gW0FudHdvcnRdKCNQbGF0Zm9ybVJhbmtpbmdCeVJlZ2lvbikNCiogV2llIEVudHdpY2tlbG4gc2ljaCBkaWUgVmVya8OkdWZlIHBybyBQbGF0Zm9ybSBpbSBsYXVmZSBkZXIgSmFocmU/IEhhYmVuIFBsYXRmb3JtZW4ga3VyeiBuYWNoIFJlbGVhc2UgZGVuIGdyw7bDn3RlbiAiSHlwZSI/IFtBbnR3b3J0XSgjU2FsZXNQZXJQbGF0Zm9ybSkNCg0KKiBCZXN0aW1tdGUgUHVibGlzaGVyIGjDpHVmZW4gc2ljaCBpbiBBbnphaGwgZGVyIFNwaWVsZSB1bmQgZGVyIFZlcmvDpHVmZW4gKHouQi4gTmludGVuZG8sIEVBLCBBY3RpdmlzaW9uIEJsaXp6YXJkKSBbQW50d29ydF0oI1B1Ymxpc2hlclJlbGVhc2VzKSAgDQoqIEdpYnQgZXMgcmVnaW9uYWxlIFVudGVyc2NoaWVkZSBpbiBkZW4gUHVibGlzaGVybj8gV2VyZGVuIFJlZ2lvbmVuaW50ZXJuZSBQdWJsaXNoZXIgRmF2b3JpdGlzaWVydD8gW0FudHdvcnRdKCNQdWJsaXNoZXJSYW5raW5nYnlSZWdpb24pDQoNCiogV2llIHNpbmQgZGllIEdlbnJlcyBkZXIgU3BpZWxlIHZlcnRlaWx0PyBIw6R1ZmVuIHNpY2ggYmVzdGltbXRlIEdlbnJlcyBiZWkgQW56YWhsIHVuZCBWZXJrYXVmc3phaGxlbj8gR2lidCBlcyBHZW5yZXMgZGllIGJlc3Nlci9zY2hsZWNodGVyIFBlcmZvcm1lbiBhbHMgc2llIHNvbGx0ZW4/IFtBbnR3b3J0XSgjR2VucmVBbW91bnRHbG9iYWwpICAgDQoqIEdpYnQgZXMgcmVnaW9uYWxlIFVudGVyc2NoaWVkZSBpbiBkZW4gR2VucmVzPyAoR2lidCBlcyBSZWdpb25lbiBkaWUgU3BlemlmaXNjaGUgR2VucmVzIEZhdm9yaXNpZXJlbiB3ZWxjaGUgaW4gYW5kZXJlbiBSZWdpb25lbiBudXIgZWluZSBnZXJpbmdlIFJvbGxlIHNwaWVsdD8pIFtBbnR3b3J0XSgjR2VucmVBbW91bnRCeVJlZ2lvbikNCg0KKiBXaWUgaGFiZW4gc2ljaCBkaWUgR2VucmVzIMO8YmVyIGRpZSBKYWhyZSBlbnR3aWNrZWx0PyBbQW50d29ydF0oI0dlbnJlQW1vdW50UGVyWWVhcikNCiogR2lidCBlcyBHZW5yZXMgZGllIG1hbCBncm/Dn2VuIEVpbmZsdXNzIGhhdHRlbiB1bmQgbnVuIEJlZGV1dHVuZ3Nsb3Mgc2luZD8gW0FudHdvcnRdKCNHZW5yZVNhbGVzUGVyR2FtZVBlclllYXIpDQoNCiogR2lidCBlcyBQdWJsaXNoZXIgZGllIGJlc3RpbW10ZSBHZW5yZXMgYmV2b3J6dWdlbiBiencuIFB1Ymxpc2hlciBkZXJlbiBHYW1lcyBlaW5lcyBiZXN0aW1tdGVuIEdlbnJlcyBzaWNoIGJlc29uZGVycyBndXQgVmVya2F1ZmVuPyBbQW50d29ydF0oI0dlbnJlQnlQdWJsaXNoZXJHbG9iYWwpDQoNCg0KKioqDQoNCiMjIyBEYXRlbiB1bmQgTGlicmFyeXMNCk5hY2ggZGVtIFZvcnN0ZWxsZW4gZGVyIERhdGVuIHVuZCBkZW0gYXVmc3RlbGxlbiBkZXIgaW5pdGlhbGVuIFRoZXNlbiBrw7ZubmVuIHdpciBudW4gbWl0IGRlbSBlaW5sZXNlbiBkZXIgRGF0ZW4gYmVnaW5uZW4uICANClp1c8OkdHpsaWNoIGVyc3RlbGxlbiB3aXIgbm9jaCBlaW5lIEZhcmJwYWxldHRlIHVuZCBpbXBvcnRpZXJlbiBkaWUgTGlicmFyeXMNCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9VFJVRSwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFfQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShmb3JjYXRzKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGtuaXRyLCB3YXJuLmNvbmZsaWN0cyA9IEZBTFNFLCBxdWlldGx5PVRSVUUpDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCmxpYnJhcnkoc3RyaW5ncikNCmxpYnJhcnkoZHlncmFwaHMpDQpsaWJyYXJ5KHh0cykNCnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyhsaWJyYXJ5KGRwbHlyKSkNCm15UGFsZXR0ZSA8LSBicmV3ZXIucGFsKDEwLCAiUGFpcmVkIikNCnZnc2FsZXMgPC0gcmVhZF9jc3YoInZnc2FsZXMuY3N2IikNCg0KYGBgDQoNCioqKg0KDQoNCiMgVmlkZW9zcGllbCByZWxlYXNlcyB7I1ZpZGVvR2FtZVJlbGVhc2VzfQ0KDQoNCiMjIFZpZGVvc3BpZWwgcmVsZWFzZXMgaW0gbGF1ZmUgZGVyIEphaHJlIHsudGFic2V0fQ0KIyMjIFJlbGVhc2VzIG5hY2ggQW56YWhsIHsjVmlkZW9HYW1lUmVsZWFzZXNBbW91bnR9DQoNClVuc2VyZSBlcnN0ZSBUaGVzZSB3YXIg4oCcV2VsY2hlIEphaHJlIHNpbmQgZGllIGJlc3RlbiBpbiBkZXIgQW56YWhsIGRlciByZWxlYXN0ZW4gR2FtZXMgdW5kIFNhbGVzP+KAnSBVbSBkaWVzZXIgRnJhZ2VzdGVsbHVuZyBhdWYgZGVuIEdydW5kIHp1IGdlaGVuIG3DvHNzZW4gd2lyIHp1ZXJzdCBlaW5tYWwgZGllIERhdGVuIGRlciBUYWJlbGxlIHZnc2FsZXMgbWl0aGlsZmUgZGVyIEZ1bmt0aW9uICpncm91cF9ieShZZWFyKSogYW5oYW5kIGRlciBKYWhyZSBadXNhbW1lbmZhc3Nlbi4gTnVuIGVyaGFsdGVuIHdpciBlaW5lIG5hY2ggZGVuIEphaHJlbiB6dXNhbW1lbmdlZmFzc3RlIFRhYmVsbGUgZGVyZW4gRWludHLDpGdlIHdpciBtaXQgZGVyIEZ1bmt0aW9uICpkcGx5cjo6c3VtbWFyaXplKEFuemFobCA9bigpKSogYWJ6w6RobGVuIHVuZCBhbHMgV2VydCBBbnphaGwgYWJzcGVpY2hlcm4uIEF1ZmdydW5kIGRlciBmw7xyIGRpZXNlIGFuYWx5c2UgRmVobGVyaGFmdGVuIERhdGVuIHZlcndlbmRlbiB3aXIgbm9jaCBkaWUgRnVua3Rpb24gKmZpbHRlcigpKiB1bSBhbGxlIGZlaGxlbmRlbiBKYWhyZXNlaW50csOkZ2Ugc293aWUgZGllIEphaHJlIDIwMjAgdW5kIDIwMTcgaGVyYXVzenVmaWx0ZXJuLiBMZXR6dGVyZSBKYWhyZSBzaW5kIGRhaGVyIGZlaGxlcmhhZnQsIGRhIGRlciBEYXRlbnNhdHogMjAxNiBlcnN0ZWxsdCB3dXJkZS4gRGllc2UgRGF0ZW4gc3BlaWNoZXJuIHdpciBhbHMgKmRhdGEuZnJhbWUqIGluIGRlciBWYXJpYWJsZSAqZ3JvdXBlZCogYWIuIEltIEZvbGdlbmRlbiB2ZXJ3ZW5kZW4gd2lyIGViZW5qZW5lcyBkYXRhLmZyYW1lIHVtIG51ciBkaWUgRWludHLDpGdlIEphaHIgdW5kIEFuemFobCB6dSBzZWxla3RpZXJlbiB1bmQgaW4gZGVyIFZhcmlhYmxlICpmaWx0ZXJlZCogYWJ6dXNwZWljaGVybi4gRGllIGVyaGFsdGVuZSBUYWJlbGxlIGhhdCBudW4gendlaSBTcGFsdGVuOiBKYWhyIHVuZCBBbnphaGwuIERlcyBXZWl0ZXJlbiBlcnN0ZWxsZW4gd2lyIHp3ZWkgd2VpdGVyZSBWYXJpYWJsZW4gKmF4KiB1bmQgKmF5KndlbGNoZSBiZWlkZSBlaW5lIExpc3RlIG1pdCBudXIgZWluZW0gQXR0cmlidXQgc2luZDog4oCcVGl0bGXigJ0uIE51biB2ZXJ3ZW5kZW4gd2lyICpwbG90X2x5KCkqIHVtIG1pdGhpbGZlIGRlciAqdHlwZSA9ICdzY2F0dGVyJyogdW5kICptb2RlID0gJ2xpbmVzJyogUGFyYW1ldGVyIGVpbiBMaW5pZW5kaWFncmFtbSB6dSBlcnN0ZWxsZW4uIEF1w59lcmRlbSBudXR6ZW4gd2lyIGRpZSAqbGF5b3V0KCkqIGZ1bmt0aW9uIHVtIGVpbmVuIFRpdGVsIHp1IGVyc3RlbGxlbiwgc293aWUgbWl0aGlsZmUgdW5zZXJlIGJlaWRlbiBWYXJpYWJsZW4gYXggdW5kIGF5IGRpZSBBY2hzZW4genUgYmVzY2hyaWZ0ZW4uDQoNCmBgYHtyIHBsb3QoQW1vdW50QnlZZWFyKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoWWVhcikgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoQW56YWhsID1uKCkpICU+JSBmaWx0ZXIoWWVhciE9J04vQScpJT4lZmlsdGVyKFllYXIhPTIwMjApICU+JSBmaWx0ZXIoWWVhciE9JzIwMTcnKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsQW56YWhsKQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJKYWhyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJBbnphaGwiDQoNCikNCg0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KHggPSB+WWVhciwgeSA9IH5BbnphaGwsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbGluZXMnLCBmaWxsID0gJ3RvemVyb3knICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJBbnphaGwgZGVyIFNwaWVsZXJlbGVhc2VzIHZvbiAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCg0KYGBgDQoNCkJldHJhY2h0ZW4gd2lyIGVpbm1hbCBkYXMgZW50c3RhbmRlbmUgRGlhZ3JhbW0uIFp3aXNjaGVuIDE5ODAgdW5kIDE5OTMgc2luZCBoaWVyIGthdW0gVW50ZXJzY2hpZWRlIGZlc3R6dXN0ZWxsZW4gdW5kIGRpZSBTY2h3YW5rdW5nZW4ga8O2bm5lbiBhdWZncnVuZCBkZXIgZ2VyaW5nZW4gWmFobCBkZXIgVmVyw7ZmZmVudGxpY2h1bmdlbiAoendpc2NoZW4gMTQgdW5kIDQ5KSB2ZXJuYWNobMOkc3NpZ3Qgd2VyZGVuLiBBYiAxOTkzIGvDtm5uZW4gd2lyIGRhbm4gZWluIHN0ZXRpZ2VzIFdhY2hzdHVtIGZlc3RzdGVsbGVuIHdlbGNoZXMgMTk5OCB2b3JlcnN0IGRlbiBIw7ZjaHN0d2VydCBlcnJlaWNodC4gSW4gZGVuIEphaHJlbiAxOTk5IHVuZCAyMDAwIGdlaHQgZGllIEFuemFobCBlcnN0IGVpbm1hbCBsZWljaHQgenVyw7xjayBiZXZvciBzaWNoIGRlciBXZXJ0IGJpcyAyMDAyIHZvbiAzNDkgYXVmIDgyOSBtZWhyIGFscyB2ZXJkb3BwZWx0LiBCaXMgMjAwNCBpc3Qgd2llZGVydW0gZWluIGxlaWNodGVyIFLDvGNrZ2FuZyBmZXN0enVzdGVsbGVuIGF1ZiB3ZWxjaGVtIGVpbiBTdGV0aWdlcyBXYWNoc3R1bSB6dW0gSMO2Y2hzdHdlcnQgdm9uIDE0MjggKDIwMDgpIHNvd2llIDE0MzEgKDIwMDkpIGZvbGd0LiBEYW5hY2ggZm9sZ3QgZWluIGV4dHJlbWVyIHVuZCBtaXQgVW50ZXJicmVjaHVuZyB2b24gMjAxNCAoNTgyKSB1bmQgMjAxNSAoNjE0KSBzdGV0aWdlciBSw7xja2dhbmcgaW4gZGVuIFJlbGVhc2UgWmFobGVuIGF1ZiBlaW5lbiBTdGFuZCB2b24gMzQ0IGltIEphaHIgMjAxNi4NCg0KU2VoZW4gd2lyIHVucyBkaWVzZSBaYWhsZW4gZWlubWFsIGdlbmF1ZXIgYW4ga29tbXQgZGllIEZyYWdlIGF1ZiBXb3JhbiBkaWVzZSBFeHRyZW1lbiBaYWhsZW4gaW4gZGVuIFZlcsO2ZmZlbnRsaWNodW5nZW4genVyw7xja3p1ZsO8aHJlbiBzaW5kPyBBbiBkaWVzZW0gUHVua3QgZGVyIEFuYWx5c2Uga8O2bm5lbiB3aXIgbnVyIHNwZWt1bGllcmVuIGRpZSBTcGl0emVuIGvDtm5udGVuIGFsbGVyZGluZ3MgYW4gZGVuIFZlcsO2ZmZlbnRsaWNodW5nZW4gZ3Jvw59lciwgZGVuIE1hcmt0IGJlc3RpbW1lbmRlbiBQbGF0dGZvcm1lbiB3aWUgZGVyIFBTMi8zLCBkZXIgWGJveCB1bmQgZGVuIFBsYXR0Zm9ybWVuIHZvbiBOaW50ZW5kbyB3aWUgR2FtZWN1YmUgb2RlciBXaWkgenVyw7xja3p1ZsO8aHJlbiBzZWluLiBIaWVyenUgYWJlciBzcMOkdGVyIFttZWhyXSgjU2FsZXNQZXJQbGF0Zm9ybSkuDQoNCg0KIyMjIFJlbGVhc2VzIG5hY2ggVmVya2F1ZnN6YWhsZW4geyNWaWRlb0dhbWVSZWxlYXNlc1NhbGVzfQ0KDQpVbSBkZW0gendlaXRlbiBUZWlsIGRlciBGcmFnZXN0ZWxsdW5nIGF1ZiBkZW4gR3J1bmQgZ2VoZW4genUga8O2bm5lbiBtw7xzc2VuIHdpciBlcm5ldXQgZGllIERhdGVuIGRlciBUYWJlbGxlIHZnc2FsZXMgbWl0aGlsZmUgZGVyIEZ1bmt0aW9uICpncm91cF9ieShZZWFyKSogYW5oYW5kIGRlciBKYWhyZSBadXNhbW1lbmZhc3Nlbi4gTnVuIGVyaGFsdGVuIHdpciB3aWVkZXIgZGllIG5hY2ggZGVuIEphaHJlbiB6dXNhbW1lbmdlZmFzc3RlIFRhYmVsbGUgZGVyZW4gRWludHLDpGdlIHdpciBtaXQgZGVyIEZ1bmt0aW9uICAqZHBseXI6OnN1bW1hcml6ZShncl9zdW0gPSBzdW0oR2xvYmFsX1NhbGVzKSkqIHp1c2FtbWVuZmFzc2VuLiBEZW0gQXVmbWVya3NhbWVuIExlc2VyIHdpcmQgYXVmZmFsbGVuIGRhcyBoaWVyIGVpbiBrbGVpbmVyIGFiZXIgZmVpbmVyIFVudGVyc2NoaWVkIHp1bSB2b3JoZXJpZ2VuIEF1ZnJ1ZiBiZXN0ZWh0LiBTdGF0dCAqQW56YWhsID1uKCkqIG51dHplbiB3aXIgaGllciAqZ3Jfc3VtID0gc3VtKEdsb2JhbF9TYWxlcykqLiBEaWVzZSBGdW5rdGlvbiBzdW1taWVydCBhbGxlIFdlcnRlIGRlciBTcGFsdGUgR2xvYmFsX1NhbGVzIGF1ZiB1bmQgc3BlaWNoZXJ0IGRlbiBkZW4gV2VydCBpbiBkaWUgU3BhbHRlICpncl9zdW0qLiBBdWZncnVuZCBkZXIgZsO8ciBkaWVzZSBhbmFseXNlIHdlaXRlcmhpbiBGZWhsZXJoYWZ0ZW4gRGF0ZW4gdmVyd2VuZGVuIHdpciBlcm5ldXQgZGllIEZ1bmt0aW9uICpmaWx0ZXIoKSogdW0gYWxsZSBmZWhsZW5kZW4gSmFocmVzZWludHLDpGdlIHNvd2llIGRpZSBKYWhyZSAyMDIwIHVuZCAyMDE3IGhlcmF1c3p1ZmlsdGVybi4gIERpZXNlIERhdGVuIHNwZWljaGVybiB3aXIgd2llZGVyIGFscyAqZGF0YS5mcmFtZSogaW4gZGVyIFZhcmlhYmxlICpncm91cGVkKiBhYi4gSW0gZm9sZ2VuZGVuIHZlcndlbmRlbiB3aXIgZWJlbmplbmVzIGRhdGEuZnJhbWUgdW0gbnVyIGRpZSBFaW50csOkZ2UgSmFociB1bmQgKmdyX3N1bSogenUgc2VsZWt0aWVyZW4gdW5kIGluIGRlciBWYXJpYWJsZSAqZmlsdGVyZWQqIGFienVzcGVpY2hlcm4uIERpZSBlcmhhbHRlbmUgVGFiZWxsZSBoYXQgbnVuIHp3ZWkgU3BhbHRlbjogSmFociB1bmQgKmdyX3N1bSouIERlc3dlaXRlcmVuIGVyc3RlbGxlbiB3aXIgZXJuZXV0IGRpZSBWYXJpYWJsZW4gKmF4KiB1bmQgKmF5Ki4gTnVuIHZlcndlbmRlbiB3aXIgKnBsb3RfbHkoKSogdW0gbWl0aGlsZmUgZGVyICp0eXBlID0gJ3NjYXR0ZXInKiB1bmQgKm1vZGUgPSAnbGluZXMnKiBQYXJhbWV0ZXIgZWluIExpbmllbmRpYWdyYW1tIHp1IGVyc3RlbGxlbi4gQXXDn2VyZGVtIG51dHplbiB3aXIgZGllICpsYXlvdXQoKSogZnVua3Rpb24gdW0gZWluZW4gdGl0ZWwgenUgZXJzdGVsbGVuLCBzb3dpZSBtaXRoaWxmZSB1bnNlcmUgYmVpZGVuIFZhcmlhYmxlbiBheCB1bmQgYXkgZGllIEFjaHNlbiB6dSBiZXNjaHJpZnRlbi4NCg0KYGBge3IgcGxvdChHYW1lU2FsZXNCeVllYXIpLCBpbmNsdWRlPVRSVUUsIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGdyb3VwX2J5KFllYXIpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKGdyX3N1bSA9IHN1bShHbG9iYWxfU2FsZXMpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLGdyX3N1bSkNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiSmFociINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiIFZlcmvDpHVmZSBwcm8gSmFociAoaW4gbWlvKSINCg0KKQ0KDQpmaWx0ZXJlZCAlPiUNCnBsb3RfbHkoeCA9IH5ZZWFyLCB5ID0gfmdyX3N1bSwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcycsIGZpbGwgPSAndG96ZXJveScgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlZpZGVvc3BpZWx2ZXJrw6R1ZmUgdm9uIDE5ODAtMjAxNiIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KDQpgYGANCg0KQmV0cmFjaHRlbiB3aXIgbnVuIGRhcyBlbnRzdGFuZGVuZSBEaWFncmFtbSBmw6RsbHQgdW5zIHp1ZXJzdCBhdWYsIGRhc3MgZXMgZGVtIHZvcmhlcmlnZW4gcmVjaHQgw6RobmxpY2ggc2llaHQuIERpZXMgaXN0IGthdW0gdmVyd3VuZGVybGljaCB1bmQgc3RlbGx0IGtlaW5lbiBuZW5uZW5zd2VydGVuIFdpc3NlbnNnZXdpbm4gZGEuIERlciB3b2hsIE5lbm5lc3dlcnRlc3RlIHVudGVyc2NoaWVkIGlzdCBkYXMgRmVobGVuIGRlcyBBbnN0aWVncywgd2VsY2hlciBpbiBkZXIgQW56YWhsIGRlciBHYW1lcmVsZWFzZXMgenVtIEphaHIgMjAxNSBmZXN0enVzdGVsbGVuIHdhci4gRHVyY2ggZGVuIGRpcmVrdGVuIFZlcmdsZWljaCBpc3QgZGllcyBhbGxlcmRpbmdzIGVpbiBndXRlciBaZWl0cHVua3QgdW0gdW5zIG1pdCB1bnNlcmVyIFp3ZWl0ZW4gVGhlc2UgYXVzZWluYW5kZXJ6dXNldHplbi4gKiJXZXJkZW4gaGV1dHp1dGFnZSBtZWhyIFNwaWVsZSBSZWxlYXN0IHVuZCBWZXJrYXVmdCBhbHMgbm9jaCAxOTgwPyIqLiBEaWVzZSBzZWhlbiB3aXIgYXVmamVkZW5mYWxsIGJlc3TDpHRpZ3Qgb2J3b2hsIEZlc3R6dXN0ZWxsZW4gaXN0LCBkYXNzIGRpZSBiZXN0ZW4gSmFocmUgc293b2hsIGluIHZlcmvDpHVmZW4gYWxzIGF1Y2ggaW4gZGVyIEFuemFobCBkaWUgSmFocmUgMjAwOCB1bmQgMjAwOSB3YXJlbi4gRGllcyBXaXJmdCBuYXTDvHJsaWNoIGRpZSBGcmFnZSBhdWYgd2FzIGRlciBHcnVuZCBmw7xyIGRpZXNlbiBWZXJsYXVmIGlzdCB1bmQgd8OkcmUgZWluIEludGVyZXNzYW50ZXIgYW5zYXR6IGbDvHIgZWluZSBbd2VpdGVyZSBBcmJlaXRdKCNBdXNibGlja0luRGllWnVrdW5mdCkuDQoNCiMjIyBWZXJrYXVmc3phaGxlbiBwcm8gU3BpZWwgDQoNCkRpZSBGcmFnZSBkaWUgV2lyIGFsbGVyZGluZ3MgYmVhbnR3b3J0ZW4ga8O2bm5lbiBpc3QgKiJXZXJkZW4gbmV1ZXJlIFNwaWVsZSBhdXRvbWF0aXNjaCBtZWhyIEdla2F1ZnQ/IiouIERhZsO8ciBrb21iaW5pZXJlbiB3aXIgZGllIGJlaWRlbiBiZXJlaXRzIFZlcndlbmRldGVuIGFuc8OkdHplLiANCldpciBmYXNzZW4gd2llZGVyIGRpZSBkYXRlbiBtaXRoaWxmZSB2b24gKmdyb3VwX2J5KFllYXIpKiBhbmhhbmQgZGVyIEphaHJlIFp1c2FtbWVuLiBEaWUgZXJoYWx0ZW5lIFRhYmVsbGUgZmFzc2VuIHdpciB3aWVkZXIgbWl0ICAqZHBseXI6OnN1bW1hcml6ZShncl9zdW0gPSBzdW0oR2xvYmFsX1NhbGVzKSkqIHp1c2FtbWVuLiBEaWVzbWFsIG51dHplbiB3aXIgamVkb2NoIGVpbmUga29tYmluYXRpb24gYXVzICpzdW0oR2xvYmFsX1NhbGVzKSogdW5kICpuKCkqLiBXaXIgYWRkaWVyZW4gZGllIFNwYWx0ZSAqR2xvYmFsX1NhbGVzKiwgdGVpbGVuIGRpZXMgZHVyY2ggZGllIEFuemFobCBkZXIgRWludHLDpGdlIHVuZCBzcGVpY2hlcm4gZGVuIFdlcnQgaW4gZGllIFNwYWx0ZSAqZ2FtZXNhbGVzKiAoKmdhbWVzYWxlcyA9IHN1bShHbG9iYWxfU2FsZXMpL24oKSopLiBEYW5hY2ggZmlsdGVybiB3aXIgZGllIERhdGVuIGVybmV1dCB1bmQgc3BlaWNoZXJuIHNpZSBhbHMgKmRhdGEuZnJhbWUqIGluIGdyb3VwZWQgYWIuIERpZXNtYWwgc2VsZWt0aWVyZW4gd2llIGRpZSBFaW50csOkZ2UgZGVyIFNwYWx0ZSBKYWhyIHNvd2llICpnYW1lc2FsZXMqIHVuZCBzcGVpY2hlcm4gc2llIGluIGRlciBWYXJpYWJsZSAqZmlsdGVyZWQqIGFiLiBadWxldHp0IGVyc3RlbGxlbiB3aXIgZXJuZXV0IGRpZSBWYXJpYWJsZW4gKmF4KiB1bmQgKmF5KiB1bmQgdmVyd2VuZGVuICpwbG90X2x5KCkqIHVtIG1pdGhpbGZlIGRlciAqdHlwZSA9ICdzY2F0dGVyJyogdW5kICptb2RlID0gJ2xpbmVzJyogUGFyYW1ldGVyIGVpbiBMaW5pZW5kaWFncmFtbSB6dSBlcnN0ZWxsZW4gc293aWUgZGllICpsYXlvdXQoKSogZnVua3Rpb24gdW0gZWluZW4gdGl0ZWwgenUgZXJzdGVsbGVuIHVuZCBtaXRoaWxmZSB1bnNlcmUgYmVpZGVuIFZhcmlhYmxlbiBheCB1bmQgYXkgZGllIEFjaHNlbiB6dSBiZXNjaHJpZnRlbi4NCg0KYGBge3IgcGxvdChTYWxlc2J5R2FtZUJ5WWVhciksIGluY2x1ZGU9VFJVRSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoWWVhcikgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoZ2FtZXNhbGVzID0gc3VtKEdsb2JhbF9TYWxlcykvbigpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLGdhbWVzYWxlcykNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiSmFociINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiVmVya8OkdWZlIHBybyBTcGllbCINCg0KKQ0KDQpmaWx0ZXJlZCAlPiUNCnBsb3RfbHkoeCA9IH5ZZWFyLCB5ID0gfmdhbWVzYWxlcywgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcycsIGZpbGwgPSAndG96ZXJveScgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlZpZGVvc3BpZWx2ZXJrw6R1ZmUgcHJvIFNwaWVsIHZvbiAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCg0KYGBgDQpTYWhlbiBzaWNoIGRpZSBiZWlkZW4gRGlhZ3JhbW1lIGbDvHIgQW56YWhsIHVuZCBWZXJrYXVmc3phaGxlbiBub2NoIHJlY2h0IMOkaG5saWNoIHN0ZWxsdCBzaWNoIGhpZXIgZWluIGRldXRsaWNoIHVudGVyc2NoaWVkbGljaGVyIFZlcmxhdWYgZGEuIElzdCBkZXIgV2VydCB6d2lzY2hlbiAxOTgwICgxLjI2KSB1bmQgMTk4MyAoMC45OCkgbm9jaCByZWxhdGl2IGdlcmluZyBzdGVpZ3QgZGllc2VyIE1hc3NpdiBmw7xyIGRpZSBKYWhyZSAxOTg0KDMuNTkpIHVuZCAxOTg1KDMuODUpIGJldm9yIGVyIDE5ODYoMS43NikgdW5kIDE5ODcoMS4zNSkgd2llZGVyIGFic2lua3QuIEdlbmF1c28gc2NobmVsbCB3aWUgZGVyIHdlcnQgYWJnZXN1bmtlbiBpc3Qgc3RlaWd0IGVyIGFsbGVyZGluZ3MgYXVjaCB3aWVkZXIgYXVmIDMuMTQoMTk4OCkgYmV2b3IgZXIgMTk4OSBkZW4gSMO2Y2hzdHN0YW5kIG1pdCA0LjMyIGVycmVpY2h0LiBEYW5hY2ggc2lua3QgZGVyIHdpZWRlciBhYiB1bSBzaWNoIG5hY2ggZWluZW0ga3VyemVuIGF1c3NjaGxhZyAxOTkyIGluIGRlbiBKYWhyZW4gYmlzIDIwMTQgYXVmIGVpbmVuIHJlbGF0aXYgc3RldGlnZW4gV2VydCBad2lzY2hlbiAwLjUgdW5kIDAuNyBlaW56dXBlbmRlbG4gZXJzdCAyMDE1IHVuZCAyMDE2IHNpbmt0IGRpZXNlciB1bnRlciAwLjUuIERpZXNlIEV4dHJlbWVuIGF1c3NjaGzDpGdlIGluIGRlbiBGcsO8aGVyZW4gSmFocmVuIGxhc3NlbiBzaWNoIG1pdCBkZXIgR2VyaW5nZW4gYW56YWhsIGRlciBTcGllbGUgZXJrbMOkcmVuLiBFaW56ZWxuZSBndXRlIGxhdWZlbmRlIFNwaWVsZSBtYWNoZW4gaGllciBub2NoIGVpbmVuIEdyb8OfdGVpbCBkZXMgTWFya3RzIGF1cyB3b2hpbmdlZ2VuIHNpY2ggbmV1ZXJlIHNwaWVsZSwgc293b2hsIGdlZ2VuIGVpbmUgR3Jvw596YWhsIHZvbiBiZXJlaXRzIGV0YWJsaWVydGVuIFNwaWVsZSBhbHMgYXVjaCBlaW5lIGdyb8OfZSBBbnphaGwgbmV1ZXIgUmVsZWFzZXMsIGR1cmNoc2V0emVuIG3DvHNzZW4uDQoNCiMjIHstfQ0KDQoqKioNCg0KIyBQbGF0Zm9ybSBBbmFseXNlIHsjUGxhdGZvcm1hbmFseXNlfQ0KDQpgYGB7ciBub3Bsb3QsIGVjaG8gPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgaW5jbHVkZSA9RkFMU0UsfQ0KdmdzYWxlcyAlPiUgDQogIHBsb3RfbHkoDQogICAgeD1+UGxhdGZvcm0sDQogICAgc3Ryb2tlPUkoImJsYWNrIiksDQogICAgbmFtZT0iQW1vdW50IGJ5IFBsYXRmb3JtIikgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZT0iQW1vdW50IGJ5IFBsYXRmb3JtIikNCnZnc2FsZXMgJT4lIA0KICBwbG90X2x5ICU+JSANCiAgYWRkX2JveHBsb3QoDQogICAgeD1+UGxhdGZvcm0sDQogICAgc3Ryb2tlPUkoImJsYWNrIiksDQogICAgbmFtZT0iQW1vdW50IGJ5IFBsYXRmb3JtIikgJT4lIA0KICBsYXlvdXQoDQogICAgdGl0bGU9IkFtb3VudCBieSBQbGF0Zm9ybSIpDQoNCnZnc2FsZXMgJT4lIA0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfYmFycygNCiAgICB4PX5HbG9iYWxfU2FsZXMsDQogICAgeT1+UGxhdGZvcm0sDQogICAgbmFtZT0iU2FsZXMgYnkgUGxhdGZvcm0gKGluIG1pbykiKSAlPiUgDQogIGxheW91dCgNCiAgICB0aXRsZT0iU2FsZXMgYnkgUGxhdGZvcm0gKGluIG1pbykiKQ0KDQpgYGANCg0KVmllZGVvc3BpZWxlIGdpYnQgZXMgaW4gZGVuIFVudGVyc2NoaWVkbGljaHN0ZW4gRmFyYmVuIHVuZCBGb3JtZW4uIFdhcyBTaWUgamVkb2NoIGFsbGUgZ2VtZWluc2FtIGhhYmVuIGlzdCwgZGFzcyBzaWUgYXVmIGVpbmVtIG1lZGl1bSBHZXNwaWVsdCB3ZXJkZW4uIFNlaSBlcyBTb255cyBQbGF5c3RhdGlvbiwgTWljcm9zb2Z0cyB4Qm94LCBOaW50ZW5kb3MgU3BpZWxla29uc29sZW4gd2llIGRpZSBXaWkgb2RlciBkZXIgZWluZmFjaGUgZGVza3RvcCBQQy4gRGllIEZyYWdlIGRpZSBTaWNoIGplZGVyIEZhbiBqZWRvY2ggc2Nob25tYWwgZ2VzdGVsbHQgaGF0IHVuZCDDvGJlciBkaWUgaMOkdWZpZyBkaXNrdXRpZXJ0IHdpcmQgaXN0IHdlbGNoZSBpc3QgZGllIEJlc3RlPyBEYSBkaWVzIGltbWVyIGltIEF1Z2UgZGVzIEJldHJhY2h0ZXJzIGxpZWd0IHZlcnN1Y2hlbiB3aXIgenVtaW5kZXN0ZW5zIHp1IGtsw6RyZW4gKldlbGNoZSBQbGF0Zm9ybSBpc3QgZGllIGJlc3RlIGluIEFuemFobCB2ZXJrw6R1ZmVuPyBXZWxjaGUgaW4gQW56YWhsIGRlciBHYW1lIFJlbGVhc2VzPyouIFp1bSBiZWFudHdvcnRlbiBkaWVzZXIgRnJhZ2UgaXN0IGRlciBWb3JoYW5kZW5lIERhdGVuc2F0eiBuaWNodCBnYW56IG9wdGltYWwgYWJlciBoaWVyenUgd2VpdGVyZXMgaW0gW0Zheml0XSgjQXVmZ2V0cmV0ZW5lUHJvYmxlbWUpLg0KDQoNCiMjIFBsYXRmb3JtYW5hbHlzZSBHbG9iYWwgey50YWJzZXR9DQoNCiMjIyBuYWNoIEFuemFobA0KDQpVbSBzaWNoIGVpbmVuIGd1dGVuIMOcYmVyYmxpY2sgw7xiZXIgZGllIFJhbmtpbmdzIGRlciBQbGF0dGZvcm1lbiB6dSB2ZXJzY2hhZmZlbiBudXR6ZW4gd2lyIGhpZXIgZWluIFBhcmV0b2RpYWdyYW1tLiBEaWVzIHNpbmQgbmFjaCBkZXIgR3LDtsOfZSBkZXIgV2VydGUgc29ydGllcnRlIFPDpHVsZW5kaWFncmFtbWUuIFp1bSBFcnN0ZWxsZW4gZGVzIERpYWdyYW1tcyBicmF1Y2hlbiB3aXIgenVlcnN0IGVpbm1hbCB3aWVkZXIgdW5zZXJlbiBEYXRlbnNhdHogZGVuIHdpciBkaWVzbWFsIG1pdGhpbGZlIGRlcyAqZ3JvdXBfYnkqIEJlZmVobHMgYW5oYW5kIGRlciAqUGxhdGZvcm0qIGdydXBwaWVyZW4uIERhbmFjaCBudXR6ZW4gd2lyIGVybmV1dCAqc3VtbWFyaXplKEFuemFobCA9bigpKiB1bSBkaWUgRWludHLDpGdlIGFienV6w6RobGVuIHVuZCBkZW4gd2VydCBhbHMgQW56YWhsIGFienVzcGVpY2hlcm4uIFVtIGRpZSBFaW50csOkZ2UgZGVyIEFuemFobCBuYWNoIHp1IHNvcnRpZXJlbiBudXR6ZW4gd2lyIHp1ZXJzdCBkZW4gQmVmZWhsICpncm91cGVkW29yZGVyKGdyb3VwZWRcJEFuemFobCksZGVjcmVhc2luZyA9IEZBTFNFXSogdW5kIHdlaXNlbiBkYXMgRXJnZWJuaXMgZGVyIG5ldWVuIFRhYmVsbGUgKk9yZGVyZWQqIHp1LiBEaWVzZXIgQmVmZWhsIHNpZWh0IHJlbGF0aXYga29tcGxleCBhdXMgbMOkc3N0IHNpY2ggamVkb2NoIHJlY2h0IGVpbmZhY2ggYXVmZHLDtnNlbG4uIE9yZGVyIHNvcnRpZXJ0IGRpZSBUYWJlbGxlIG5hY2ggZGVyIGdlZ2ViZW5lbiBTcGFsdGUgdW5kIGRlciBQYXJhbWV0ZXIgKmRlY3JlYXNpbmcgPSogZ2lidCBhbiBvYiBkZXIgZ3LDtsOfdGUgV2VydCBhbSBBbmZhbmcgb2RlciBFbmRlIHN0ZWhlbiBzb2xsLiBEYXMgRG9sbGFyIFplaWNoZW4gc2VsZWt0aWVydCBoaWVyYmVpIGRpZSBTcGFsdGUgbWl0IGRlbSBkYWhpbnRlcnN0ZWhlbmRlbiBOYW1lIGF1cyBkZXIgdm9yaGVyIHN0ZWhlbmRlbiBUYWJlbGxlIGdldHJldSBuYWNoIGRlbSBTY2hlbWEgKlRhYmVsbGVcJFNwYWx0ZSouIERhbmFjaCBtw7xzc2VuIHdpciBub2NoIGRpZSBTcGFsdGUgKlBsYXRmb3JtKiBhbHMgZmFrdG9yIGVpbmxlc2VuIHdlbGNoZXMgd2lyIG1pdCBkZW0gQmVmZWhsICphc19mYWN0b3Iob3JkZXJlZFwkUGxhdGZvcm0pKiB0dW4uIERhbmFjaCBlcnN0ZWxsZW4gd2lyIHVuc2VyZSBiZWlkZW4gVmFyaWFibGVuIGF4IHVuZCBheSB6dXIgQWNoc2VuYmVzY2hyaWZ0dW5nLiBOdW4ga29tbWVuIHdpciB6dXIgZWlnZW50bGljaGVuIERpYWdyYW1tZXJzdGVsbHVuZy4gV2lyIGdlYmVuIGRpZSBUYWJlbGxlICpvcmRlcmVkKiB3ZWl0ZXIgYW4gKnBsb3RfbHkoKSogdW5kIG51dHplbiAqYWRkX2JhcnMqIHVtIGVpbiBCYWxrZW5kaWFncmFtbSB6dSBlcnN0ZWxsZW4uIERlciB1bnRlcnNjaGllZCB6d2lzY2hlbiBCYWxrZW4gdW5kIFBhcmV0b2RpYWdyYW1tIGxpZWd0IGhpZXJiZWkgaW4gZGVyIFBhcmFtZXRlcsO8YmVyZ2FiZS4gU2NoYXVlbiB3aXIgdW5zIGRpZSByZWxldmFudGVuIFRlaWxlIGVpbm1hbCBnZW5hdWVyIGFuLiBEZXIgaW50ZXJlc3NhbnRlIFRlaWwgcGFzc2llcnQgaGllcmJlaSBiZWkgZGVyIHp1d2Vpc3VuZyBkZXIgWC1BY2hzZSB1bmQgaGllciBzZWhlbiB3aXIgYXVjaCBkZW4gR3J1bmQgZsO8ciB1bnNlcmUgdm9yaGVyaWdlIHVtd2FuZGx1bmcgZGVyIFNwYWx0ZSBQbGF0Zm9ybSB6dSBlaW5lbSBmYWt0b3IuICp4PX5mY3RfcmVvcmRlcihQbGF0Zm9ybSxBbnphaGwsIC5kZXNjPSJ0cnVlIikseT1+QW56YWhsKiBXaXIgbnV0emVuIGRlbiBCZWZlaGVsICpmY3RfcmVvcmRlcigpKiB1bSBkaWUgUGxhdGZvcm1lbiBuYWNoIGRlciBBbnphaGwgc29ydGllcnQgaGVyIGFuenVvcmRuZW4uIERlciBlcnN0ZSBQYXJhbWV0ZXIgaXN0IGhpZXJiZWkgZGllIHp1IHNvcnRpZXJlbmRlIFNwYWx0ZSwgZGVyIHp3ZWl0ZSBkaWUgbmFjaCBkZXIgc29ydGllcnQgd2VyZGVuIHNvbGwuIERlciBQYXJhbWV0ZXIgLmRlc2Mgc3RlaHQgZGVzY2VuZGluZyB1bmQgYmVzdGltbXQgd2llIHNvcnRpZXJ0IHdlcmRlbiBzb2xsLCBpbiB1bnNlcmVtIGZhbGwgZGVyIGdyw7bDn3RlIFdlcnQgenVlcnN0LiBadSBndXRlciBsZXR6dCBnZWJlbiB3aXIgZGVtIERpYWdyYW1tIG5vY2ggZWluZW4gTmFtZW4sIHdlaXNlbiBkaWUgRmFyYnBhbGV0dGUgenUgdW5kIHNldHplbiBkYXMgTGF5b3V0IG1pdCBkZW0gVGl0ZWwgc293aWUgdW5zZXJlbiBiZWlkZW4gQWNoc2VuYmVzY2hyaWZ0dW5nZW4uDQoNCmBgYHtyIHBsb3QsIGVjaG8gPSBUUlVFLG1lc3NhZ2U9RkFMU0UscmVzdWx0cz0nbWFya3VwJyx9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUGxhdGZvcm0pICU+JSANCiAgc3VtbWFyaXplKEFuemFobCA9bigpKSANCg0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkQW56YWhsKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQbGF0Zm9ybSA8LSBhc19mYWN0b3Iob3JkZXJlZCRQbGF0Zm9ybSkNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQbGF0Zm9ybSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiQW56YWhsIg0KKQ0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfYmFycyh4PX5mY3RfcmVvcmRlcihQbGF0Zm9ybSxBbnphaGwsIC5kZXNjPSJ0cnVlIiksDQogICAgICAgICAgIHk9fkFuemFobCwNCiAgICAgICAgICAgbmFtZT0iU3BpZWxlYW56YWhsIHBybyBQbGF0Zm9ybSIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNwaWVsZWFuemFobCBwcm8gUGxhdGZvcm0iLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgIA0KICAgICAgICAgKQ0KYGBgDQoNCkJlaW0gQmV0cmFjaHRlbiBkZXMgRGlhZ3JhbW1zIGVya2VubmVuIHdpciBkYXMgd2VkZXIgZ2FueiBhbHRlIG5vY2ggZ2FueiBuZXVlIFBsYXRmb3JtZW4gZGllIE5hc2Ugdm9ybmUgaGFiZW4uIEFuIGRlbiBlcnN0ZW4gYmVpZGVuIFN0ZWxsZW4gdW5kIHdlaXQgYWJnZXNjaGxhZ2VuIHZvbSBSZXN0IGRlciBQbGF0Zm9ybWVuIGZpbmRlbiBzaWNoIGhpZXIgZGVyIERTIHZvbiBOaW50ZW5kbyAoMjE2MykgdW5kIGRpZSBQbGF5c3RhdGlvbiAyIHZvbiBTb255ICgyMTYxKS4gRGllcyBpc3Qgd2VpdGVyIG5pY2h0IFZlcnd1bmRlcmxpY2ggZGEgYmVpZGUgYXVjaCBkaWUgS29uc29sZW4gc2luZCBkaWUgc2ljaCBbV2VsdHdlaXQgYW0gYmVzdGVuIHZlcmthdWZ0IGhhYmVuXShodHRwczovL2RlLnN0YXRpc3RhLmNvbS9zdGF0aXN0aWsvZGF0ZW4vc3R1ZGllLzE2MDU0OS91bWZyYWdlL2FuemFobC1kZXItd2VsdHdlaXQtdmVya2F1ZnRlbi1zcGllbGtvbnNvbGVuLW5hY2gta29uc29sZW50eXBlbi8pLiBFaW4gd2VpdGVyZXIgR3J1bmQgZsO8ciBkZXJlbiBob2hlIFNwaWVsZWFuemFobCBpc3QgdmVybXV0bGljaCBhdWNoIGRlcmVuIFN0ZWxsdW5nIGFscyBQbGF0emhpcnNjaGUgaW0gS29uc29sZW4tIGJ6dy4gSGFuZGhlbGRtYXJrdC4gV2VpdGVyaGluIGvDtm5uZW4gd2lyIGVya2VubmVuIGRhcyBlcyBtZWlzdCBkaWUgw6RsdGVyZSBHZW5lcmF0aW9uZW4gZWluZXIgS29uc29sZSBzaW5kIGRpZSBtZWhyIFNwaWVsZSBoYWJlbi4gRGllIFBsYXlzYXRhdGlvbiAyIGhhdCBiZWlzcGllbHN3ZWlzZSBtZWhyIFNwaWVsZSBhbHMgUFMzIHVuZCBQUzQsIGRpZSBYYm9YMzYwIG1laHIgYWxzIGRpZSB4Qm94T25lIHVuZCBkZXIgRFMgbWVociBhbHMgZGVyIDNEUy4gRGllcyBzY2hlaW50IGplZG9jaCBuaWNodCBhdWYgZGllIGVyc3RlIEdlbmVyYXRpb24genV6dXRyZWZmZW4uIERpZSBQbGF5c3RhdGlvbiBoYXQgbWVociB2ZXJrw6R1ZmUgYWxzIGRpZSBQUzQgYWJlciB3ZW5pZ2VyIGFscyBQUzMgdW5kIFBTMi4gRGllIFhib3ggbWVociBhbHMgZGllIFhib3hPbmUgYWJlciB3ZW5pZ2VyIGFscyBkaWUgWGJveDM2MC4NCg0KDQojIyMgbmFjaCBWZXJrYXVmc3phaGxlbg0KDQpTY2hhdWVuIHdpciB1bnMgbnVuIGRpZSBWZXJrYXVmc3phaGxlbiBkZXIgU3BpZWxlIGRlciBlaW56ZWxuZW4gUGxhdGZvcm1lbiBhbi4gV2lyIHZlcndlbmRlbiBoaWVyIHdpZWRlciBlaW4gUGFyZXRvZGlhZ3JhbW0gdW5kIGdlaGVuIMOkaG5saWNoIGRlcyB2b3JoZXJpZ2VuIERpYWdyYW1tcyB2b3IuIFp1ZXJzdCBudXR6ZW4gd2lyIHdpZWRlciBkaWUgKmdyb3VwX2J5KiBGdW5rdGlvbiB1bSBuYWNoIGRlbiBQbGF0Zm9ybWVuIHp1IGdydXBwaWVyZW4uIERhIHdpciBudW4gYWJlciBkaWUgVmVya2F1ZnN6YWhsZW4gYmV0cmFjaHRlbiB3b2xsZW4gbnV0emVuIHdpciAqc3VtbWFyaXplKCkqIGF1ZiBkaWUgKkdsb2JhbF9TYWxlcyogU3BhbHRlLiBOdW4gbnV0emVuIHdpciBkaWUgKnJlbmFtZSgpKiBmdW5rdGlvbiB1bSBkaWUgc28gZW50c3RhbmRlbmUgU3BhbGUgKnN1bShHbG9iYWxfU2FsZXMpKiBpbiAqR2xvYmFsX1NhbGVzKiB1bXp1YmVuZW5uZW4uIERpZXMgaGF0IGtlaW5lbiB3ZWl0ZXJlbiBOdXR6ZW4gYXXDn2VyIHVucyBpbSBzcMOkdGVyZW4gVmVybGF1ZiBkaWUgUmVmZXJlbnppZXJ1bmcgZGVyIFNwYWx0ZSBlaW5mYWNoZXIgenUgbWFjaGVuLiBVbSBzcMOkdGVyIG5hY2ggZGllc2VyIG5ldSBlcnN0ZWxsdGVuIFNwYWx0ZSBzb3J0aWVyZW4genUga8O2bm5lbiBtw7xzc2VuIHdpciBkaWVzZSB6dWVyc3QgaW4gZWluZW4gVmVjdG9yIHVtd2FuZGVsbi4gRGllcyB0dW4gd2lyIG1pdCBkZW0gQmVmZWhsICpncm91cGVkXCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkXCRHbG9iYWxfU2FsZXMpKi4gTnVuIGvDtm5uZW4gd2lyIGRpZSBUYWJlbGxlIHNvcnRpZXJlbiB1bmQgaW4gZGVyIFZhcmlhYmxlIG9yZGVyZWQgYWJzcGVpY2hlcm4gDQoqb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWRcJEdsb2JhbF9TYWxlcyksIGRlY3JlYXNpbmcgPSBGQUxTRV0qLiBBbHMgbGV0enRlbiBTY2hyaXR0IGJldm9yIGVzIGFuIGRpZSBlcnN0ZWxsdW5nIGRlcyBEaWFncmFtbXMgZ2VodCB3YW5kZWxuIHdpciBub2NoIGRpZSBTcGFsdGUgUGxhdGZvcm0gaW4gZWluZW4gRmFjdG9yIHVtICpvcmRlcmVkJFBsYXRmb3JtIDwtIGFzX2ZhY3RvcihvcmRlcmVkXCRQbGF0Zm9ybSkqIHVuZCBlcnN0ZWxsZW4gZXJuZXV0IHVuc2VyZSBBY2hzZW5iZXNjaHJpZnR1bmdlbiBheCB1bmQgYXkuIFp1ciBlcnN0ZWxsdW5nIGRlcyBEaWFncmFtbXMgw7xiZXJnZWJlbiB3aXIgdW5zZXJlICpvcmRlcmVkKiBUYWJlbGxlIGFuIGRpZSAqcGxvdF9seSgpKiBmdW5rdGlvbiB1bmQgbnV0emVuICphZGRfYmFycyogdW0gZWluIEJhbGtlbmRpYWdyYW1tIHp1IGVyc3RlbGxlbi4gSGllciB2ZXJ3ZW5kZW4gd2lyIHdpZWRlciBkaWUgUGFyYW1ldGVyICp4PX5mY3RfcmVvcmRlcihQbGF0Zm9ybSxHbG9iYWxfU2FsZXMsIC5kZXNjPSJ0cnVlIiksIHk9fkdsb2JhbF9TYWxlcyogdW0gZGVuIHggd2VydCwgYWxzbyBkaWUgUGxhdGZvcm1lbiBuYWNoIGRlbiBHbG9iYWwgU2FsZXMgenUgc29ydGllcmVuIGJldm9yIHdpciBkZW4gbmFtZW4gdW5kIGRpZSBGYXJiZSBkZXMgRGlhZ3JhbW1zIHNldHplbi4gWnUgZ3V0ZXIgTGV0enQgYmVudXR6ZW4gd2lyIG5vY2ggZGllIExheW91dCBmdW5rdGlvbiB1bSBkZW0gRGlhZ3JhbW0gZWluZW4gVGl0ZWwgenUgZ2ViZW4gdW5kIHVuc2VyZSBiZWlkZW4gQWNoc2VuYmVzY2hyaWZ0dW5nZW4genUgZXJzdGVsbGVuLg0KDQpgYGB7ciBwbG90KFBsYXRmb3JtUmFua2luZ19HbG9iYWwpLCBlY2hvID0gVFJVRSxtZXNzYWdlPUZBTFNFLHJlc3VsdHM9J21hcmt1cCcsfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFBsYXRmb3JtKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQbGF0Zm9ybSA8LSBhc19mYWN0b3Iob3JkZXJlZCRQbGF0Zm9ybSkNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQbGF0Zm9ybSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiVmVya2F1ZnN6YWhsZW4gKGluIG1pbykiDQoNCikNCg0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9iYXJzKHg9fmZjdF9yZW9yZGVyKFBsYXRmb3JtLEdsb2JhbF9TYWxlcywgLmRlc2M9InRydWUiKSwNCiAgICAgICAgICAgeT1+R2xvYmFsX1NhbGVzLA0KICAgICAgICAgICBuYW1lPSJWZXJrYXVmc3phaGxlbiBuYWNoIFBsYXRmb3JtIiAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iVmVya2F1ZnN6YWhsZW4gbmFjaCBQbGF0Zm9ybSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQpTY2hhdWVuIHdpciB1bnMgZGFzIEVudHN0YW5kZW5lIERpYWdyYW1tIGVpbm1hbCBhdWYgZmFsbGVuIHVucyBkaXJla3QgendlaSBEaW5nZSBhdWYuIFp1bSBlaW5lbiBmZWhsdCBkZXIgTmludGVuZG8gRFMgYXVmIGRlbSBTcGl0emVucGxhdHogenVzYW1tZW4gbWl0IGRlciBQUzIgdW5kIGlzdCBudXIgYXVmIFBsYXR6IDUsIHp1bSBhbmRlcmVuIGlzdCBkZXIgVW50ZXJzY2hpZWQgendpc2NoZW4gZGVuIFNwaXR6ZW5wbMOkdHplbiBiencgZGVtIFNwaXR6ZW5wbGF0eiB1bmQgZGVtIHJlc3QgZGVyIHRvcCA1IGRldXRsaWNoIGdlcmluZ2VyLiBXYXJlbiBlcyBiZWkgZGVyIFNwaWVsZWFuemFobCBub2NoIGZhc3QgNDAlIHVudGVyc2NoaWVkIHp3aXNjaGVuIHBsYXR6IDEvMiB1bmQgcGxhdHogMy00IHNvIHNpbmQgZXMgaGllciBudXIga25hcHAgMjAlLiBEaWUgUmVzdGxpY2hlbiBwbMOkdHplIGRlciBUb3AgNSBzaW5kIGFsbGVyZGluZ3MgZ3LDtsOfdGVudGVpbHMgZ2xlaWNoIGdlYmxpZWJlbi4gWnVzw6R0emxpY2ggenVtIGFic2Fja2VuIGRlcyBOaW50ZW5kbyBEUyB2b24gcGxhdHogMSBhdWYgcGxhdHogNSBoYXQgbnVyIGRpZSBYYm9YMzYwIGlocmUgUG9zaXRpb24gaW4gZGVyIFJhbmdsaXN0ZSB2ZXLDpG5kZXJ0Lg0KDQojIyB7LX0NCg0KIyMjIyMgKkhhYmVuIMOEbHRlcmUgUGxhdGZvcm1lbiBBdXRvbWF0aXNjaCBtZWhyIFNwaWVsZSB1bmQgVmVya8OkdWZlPyogeyNQbGF0Zm9ybVJhbmtpbmdHbG9iYWxfRW5kfQ0KDQpCZWltIEJldHJhY2h0ZW4gYmVpZGVyIERpYWdyYW1tZSBvZGVyIHNvZ2FyIG51ciBlaW5lbSBkZXIgRGlhZ3JhbW1lIGVya2VubnQgZGVyIEF1Zm1lcmtzYW1lIEJldHJhY2h0ZXIgcmVsYXRpdiBzY2huZWxsIGRhcyBoaWVyIGtlaW5lIFBhdXNjaGFsYW50d29ydCBhdWYgZGllc2UgRnJhZ2VzdGVsbHVuZyBtw7ZnbGljaCBpc3QuIERpZXMgaXN0IGFiZXIgaXJnZW5kd2llIHp1IGVyd2FydGVuIGdld2VzZW4gZXMgZ2lidCBzbyB2aWVsZSBGYWt0b3JlbiBkaWUgZGVuIEVyZm9sZyBlaW5lciBiZXN0aW1tdGVuIFBsYXRmb3JtIGJlc3RpbW1lbiB1bmQgZXMgaXN0IHVubcO2Z2xpY2ggZGllc2VzIGFuIGVpbmVtIEZha3RvciBmZXN0enVsZWdlbi4gV3dlbGNoZSBGcmFnZSB3aXIgYWxsZXJkaW5ncyBiZWFudHdvcnRlbiBrb25udGVuLCB6dW1pbmRlc3RlbnMgdGVpbHdlaXNlLCBpc3QgZGllIEZyYWdlIG5hY2ggZGVyICJiZXN0ZW4gUGxhdGZvcm0uIERpZSAqKlBTMioqIGlzdCBzb3dvaGwgd2VpdCBvYmVuIGluIGRlciBTcGllbGVhbnphaGwsIGFscyBhdWNoIFNwaXR6ZW5yZWl0ZXIgaW4gZGVuIEdhbXZlcmvDpHVmZW4uIERlciBOaW50ZW5kbyBEUyBpc3QgendhciBpbiBkZXIgU3BpZWxlYW56YWhsIHNvZ2FyIGtuYXBwIHZvciBkZXIgUFMyIGluIGRlbiB2ZXJrw6R1ZmVuIGFiZXIgd2VpdCBhYmdlc2NobGFnZW4gYXVmIFBsYXR6IDUuIEF1c3NjaGxhZ2dlYmVuZGVyIGFscyB2ZXJnbGVpY2hzYXJndW1lbnQgd8OkcmUgamVkb2NoIGRpZSBBbnphaGwgZGVyIFZlcmthdWZ0ZW4gU3BpZWxlIHBybyBTcGllbCBkb2NoIHdlaXRlcmVzIGhpZXJ6dSBpbSBbQXVzYmxpY2sgaW4gZGllIFp1a3VuZnRdKCNBdXNibGlja0luRGllWnVrdW5mdCkNCg0KT2ZmZW5zaWNodGxpY2ggaXN0IGVpbiBEYXRlbnNhdHogenUgQW56YWhsIGRlciBTcGllbGV2ZXJrw6R1ZmUgdm9yYWxsZW0gZWluIHNvIGzDvGNrZW5oYWZ0ZXIgbmljaHQgb3B0aW1hbCBhYmVyIGRhenUgd2VpdGVyZXMgaW0gW0Zheml0XSgjQXVmZ2V0cmV0ZW5lUHJvYmxlbWUpLg0KDQoqKioNCg0KIyBSZWdpb25hbGUgVW50ZXJzY2hpZWRlIGluIGRlbiBWZXJrYXVmc3phaGxlbiBkZXIgUGxhdGZvcm1lbiB7I1BsYXRmb3JtUmFua2luZ0J5UmVnaW9ufQ0KDQpEYSB3aXIgbnVuIGdla2zDpHJ0IGhhYmVuIHdlbGNoZSBQbGF0Zm9ybWVuIGRpZSBOYXNlIHZvcm5lIGhhYmVuIHfDpHJlIGVzIGRvY2ggSW50ZXJlc3NhbnQgaGVyYXVzenVmaW5kZW4gb2IgZXMgUmVnaW9uYWxlIHVudGVyc2NoaWVkZSBnaWJ0Lg0KKkZhdm9yaXNpZXJlbiB2ZXJzY2hpZWRlbmUgUmVnaW9uZW4gdmVyc2NoaWVkZW5lIFBsYXRmb3JtZW4/IFZlcmthdWZlbiBkaWUgUmVnaW9uZW5oZWltaXNjaGVuIFBsYXRmb3JtZW4gYXV0b21hdGlzY2ggYXVjaCBkaWUgbWVpc3RlbiBTcGllbGU/Kg0KDQpIaWVyYmVpIGvDtm5uZW4gd2lyIG5hdMO8cmxpY2ggbnVyIGRpZSBWZXJrYXVmc3phaGxlbiBoZXJhbnppZWhlbi4gVGhlb3JldGlzY2ggd8OkcmUgYXVjaCBlaW4gVmVyZ2xlaWNoIGluIGFuemFobCBkZXIgU3BpZWxlIG3DtmdsaWNoIHfDvHJkZSBhYmVyIGRpZXNlIEFyYmVpdCBTcHJlbmdlbiBkYSBkZXIgRGF0ZW5zYXR6IGRpZXNlIEluZm9ybWF0aW9uZW4gbmljaHQgb2huZSB3ZWl0ZXJlcyBbaGVyZ2lidF0oI0F1ZmdldHJldGVuZVByb2JsZW1lKS4NClp1bSBCZWFudHdvcnRlbiBkaWVzZXIgRnJhZ2UgYmVudXR6ZW4gd2lyIGVybmV1dCBQYXJldG9kaWFncmFtbWUgdW5kIHVtIHNpY2ggZWluZW4gR3JvYmVuIMO8YmVyYmxpY2sgenUgc2NoYWZmZW4gS3JlaXNkaWFncmFtbWUuIERpZXNlIGhhYmVuIGlocmUgZWlnZW5lbiBbUHJvYmxlbWVdKCNBdWZnZXRyZXRlbmVQcm9ibGVtZSkgYmlldGVuIHVucyBhYmVyIGVpbiBndXRlcyBUb29sIHp1ciBncm9iZW4gw7xiZXJzaWNodCDDvGJlciBkaWUgUHJvemVudHVhbHZlcnRlaWx1bmcgZGVyIEtvbnNvbGVuIHVuZCBicmluZ3QgZXR3YXMgQWJ3ZWNoc2x1bmcgaW4gZGllc2UgYmlzaGVyIHNlaHIgQmFsa2VuZGlhZ3JhbW0gbGFzdGlnZSBhdXNhcmJlaXR1bmcuDQoNCltFaW56dXdlbmRlbiBoaWVyYmVpIGlzdF0oI0F1ZmdldHJldGVuZVByb2JsZW1lKSwgZGFzcyBkaWUgUmVnaW9uZW4gbmF0w7xybGljaCB1bnRlcnNjaGllZGxpY2ggdmllbGUgRWlud29obmVyIGhhYmVuLkVpbiB2ZXJnbGVpY2ggZGVyIGFic29sdXRlbiBTYWxlc3dlcnRlIGlzdCBoaWVyYmVpIG5hdMO8cmxpY2ggbnVyIHdlbmlnIGF1c3NjaGxhZ2dlYmVuZCB6ZWlndCBhYmVyIGVpbmVuIGdlbmVyZWxsZW4gYmVsaWVidGhlaXRzdHJlbmQgZGVyIEtvbnNvbGVuIGluIGRlbiBlaW56ZWxuZW4gUmVnaW9uZW4gYXVmLg0KDQojIyBQbGF0Zm9ybXZlcmdsZWljaCB7LnRhYnNldH0NCg0KIyMjIEJhbGtlbmRpYWdyYW1tZSB7LnRhYnNldH0NCg0KRGllIEVyc3RlbGx1bmcgZGVyIFBhcmV0b2RpYWdyYW1tZSB3ZXJkZSBpY2ggYW4gZGllc2VyIFN0ZWxsZSBuaWNodCBtZWhyIGdlbmF1ZXIgZXJsw6R1dGVybiwgZGEgZGFzIEdydW5kcHJpbnppcCB3ZWl0ZXJoaW4gZGFzIGdsZWljaGUgYmxlaWJ0IGVpbnppZ2VyIHVudGVyc2NoaWVkIHp3aXNjaGVuIGRlbiB2ZXJzY2hpZWRlbmVuIERpYWdyYW1tZW4gaXN0IGhpZXJiZWkgZGVyIHdlcnQgaW4gZGVyIHN1bW1hcml6ZSBGdW5rdGlvbiAqc3VtbWFyaXplKHN1bShFVV9TYWxlcykpKiBFVV9TYWxlcyBmw7xyIEVVIE5BX1NBTEVTIGbDvHIgVVMgdW5kIEpQX1NBTEVTIGbDvHIgSmFwYW4gc293aWUgZGVyIFRpdGVsIHVuZCBkaWUgQWNoc2VuYmVzY2hyaWZ0dW5nZW4uIEVpbmUgZ2VuYXVlcmUgRXJsw6R1dGVydW5nIHp1ciBFcnN0ZWxsdW5nIHZvbiBQYXJldG9kaWFncmFtbWVuIGdpYnQgZXMgW2hpZXJdKCNQbGF0Zm9ybWFuYWx5c2UpLg0KDQojIyMjIEV1cm9wYQ0KYGBge3IgcGxvdChQbGF0Zm9ybVJhbmtpbmdfRVUxKSwgZWNobyA9IFRSVUUsbWVzc2FnZT1GQUxTRSxyZXN1bHRzPSdtYXJrdXAnLH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQbGF0Zm9ybSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKEVVX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oRVVfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFBsYXRmb3JtIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFBsYXRmb3JtKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlBsYXRmb3JtIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJFVSB2ZXJrw6R1ZmUgKGluIG1pbykiDQoNCikNCg0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9iYXJzKHg9fmZjdF9yZW9yZGVyKFBsYXRmb3JtLEdsb2JhbF9TYWxlcywgLmRlc2M9InRydWUiKSwNCiAgICAgICAgICAgeT1+R2xvYmFsX1NhbGVzLA0KICAgICAgICAgICBuYW1lPSJFVSBWZXJrYXVmc3phaGxlbiBwcm8gUGxhdGZvcm0iICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJFVSBWZXJrYXVmc3phaGxlbiBwcm8gUGxhdGZvcm0iLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KSGF0dGUgaW0gR2xvYmFsZW4gZHVyY2hzY2huaXR0IGRpZSBQUzIgbm9jaCBkZXV0bGljaCBkaWUgTmFzZSB2b3JuZSBpc3QgaW4gRVUgZGllIFBTMyAoMzQzLjcxKSBub2NoIHZvciBkZXIgUFMyICgzMzkuMjkpIHVuZCBkaWVzZSBoYWJlbiBiZWlkZSBub2NoIGVpbmVuIFJlY2h0IHdlaXRlbiBWb3JzcHJ1bmcgYXVmIFBsYXR6IDMgKDI4MC41OCkgdW5kIDQgKDI2OC4zOCkgd2VsY2hlIHJlc3Bla3RpdmUgdm9uIGRlciBYYm94MzYwIHVuZCBkZXIgV2lpIGJlbGVndCB3ZXJkZW4uIERpZSBQbGF5c3RhdGlvbiAxICgyMTMuNikgc2ljaGVydCBzaWNoIGluIEV1cm9wYSBlaW5lbiBwbGF0eiBpbiBkZW4gdG9wIDUgdW5kIGF1Y2ggZGllIFBTNCAoMTIzLjcpIHLDvGNrdCBlaW5lbiBQbGF0eiBuYWNoIFZvcm5lLiBEZW4gd29obCBncsO2w590ZW4gU3BydW5nIGxlZ3QgYWxsZXJkaW5ncyBkZXIgUEMgKDEzOS42OCkgaGluLiBJc3QgZGllc2VyIEdsb2JhbCBub2NoIGF1ZiBQbGF0eiAxMCBzbyBiZWxlZ3QgZXIgaW4gRXVyb3BhIHBsYXR6IDcuIEF1Y2ggYXXDn2VyaGFsYiBkZXIgVG9wIDEwIGdpYnQgZXMgZWluaWdlIHZlcnNjaGllYnVuZ2VuIGF1ZmdydW5kIGRlcyBlaGVyIEdlcmluZ2VyZW4gTWFya2V0c2hhcmVzIHNlaGVuIHdpciBoaWVyIGFsbGVyZGluZ3Mgdm9uIGVpbmVyIGdlbmF1ZXJlbiBBbmFseXNlIGFiLiBadXNhbW1lbmZhc3NlbmQga8O2bm5lbiB3aXIgYWxzbyBzYWdlbiBkYXMgRXVyb3BhIFNvbnkga29uc29sZW4gc293aWUgZGVuIFBjIMO8YmVyZHVyY2hzY2huaXR0bGljaCBnZXJuZSBOdXR6ZW4uDQoNCiMjIyMgTm9yZC1BbWVyaWthDQpgYGB7ciBwbG90KFBsYXRmb3JtUmFua2luZ19OQTEpLCBlY2hvID0gVFJVRSxtZXNzYWdlPUZBTFNFLHJlc3VsdHM9J21hcmt1cCcsfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFBsYXRmb3JtKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oTkFfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShOQV9TYWxlcykiDQogICAgKQ0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCm9yZGVyZWQgPC0gZ3JvdXBlZFtvcmRlcihncm91cGVkJEdsb2JhbF9TYWxlcyksIGRlY3JlYXNpbmcgPSBGQUxTRV0NCm9yZGVyZWQkUGxhdGZvcm0gPC0gYXNfZmFjdG9yKG9yZGVyZWQkUGxhdGZvcm0pDQoNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiUGxhdGZvcm0iDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIk5BIHZlcmvDpHVmZSAoaW4gbWlvKSINCg0KKQ0KDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoUGxhdGZvcm0sR2xvYmFsX1NhbGVzLCAuZGVzYz0idHJ1ZSIpLA0KICAgICAgICAgICB5PX5HbG9iYWxfU2FsZXMsDQogICAgICAgICAgIG5hbWU9Ik5BIFZlcmthdWZzemFobGVuIHBybyBQbGF0Zm9ybSIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9Ik5BIFZlcmthdWZzemFobGVuIHBybyBQbGF0Zm9ybSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQpJbSBkaXJla3RlbiBWZXJnbGVpY2ggbWl0IEVVIGbDpGxsdCBoaWVyIHNvZm9ydCBpbnMgQXVnZSwgZGFzcyBkaWUgUGxheXN0YXRpb24gMiAoNTgzLjg0KSB6d2FyIHdlaXRlcmhpbiB2b24gZGVtIGVyc3RlbiBQbGF0eiB2ZXJkcsOkbmd0IHd1cmRlLCBNaWNyb3NvZnRzIFhib3gzNjAgKDYwMS4wNSkgaGllciBTb255cyBQbGF5c3RhdGlvbiAzICgzOTIuMjYpIGFsbGVyZGluZ3MgYXVmIGRlbSBlcnN0ZW4gUGxhdHogYWJsw7ZzdC4gQXVjaCBkaWUgV2lpICg1MDcuNzEpIGhhdCBlcmtlbm5iYXIgbWVociBWZXJrw6R1ZmUgYWxzIG5vY2ggaW4gRXVyb3BhLiBQUzQgKDk2LjgpIHVuZCBQQyAoOTMuMjgpIHNwaWVsZSB2ZXJrYXVmZW4gc2ljaCBpbiBOb3JkLUFtZXJpa2EgZGV1dGxpY2ggd2VuaWdlciBhbHMgaW4gRXVyb3BhIHdvaGluZ2VnZW4gZGllIFJlc3RsaWNoZW4gUGxhdGZvcm1lbiBncsO2w590ZW50ZWlscyDDhGhubGljaCB2ZXJ0ZWlsdCBibGVpYmVuLg0KDQojIyMjIEphcGFuDQpgYGB7ciBwbG90KFBsYXRmb3JtUmFua2luZ19KUDEpLCBlY2hvID0gVFJVRSxtZXNzYWdlPUZBTFNFLHJlc3VsdHM9J21hcmt1cCcsfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFBsYXRmb3JtKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oSlBfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShKUF9TYWxlcykiDQogICAgKQ0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCm9yZGVyZWQgPC0gZ3JvdXBlZFtvcmRlcihncm91cGVkJEdsb2JhbF9TYWxlcyksIGRlY3JlYXNpbmcgPSBGQUxTRV0NCm9yZGVyZWQkUGxhdGZvcm0gPC0gYXNfZmFjdG9yKG9yZGVyZWQkUGxhdGZvcm0pDQoNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiUGxhdGZvcm0iDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkpQIHZlcmvDpHVmZSAoaW4gbWlvKSINCg0KKQ0KDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoUGxhdGZvcm0sR2xvYmFsX1NhbGVzLCAuZGVzYz0idHJ1ZSIpLA0KICAgICAgICAgICB5PX5HbG9iYWxfU2FsZXMsDQogICAgICAgICAgIG5hbWU9IkpQIFZlcmthdWZzemFobGVuIHBybyBQbGF0Zm9ybSIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IkpQIFZlcmthdWZzemFobGVuIHBybyBQbGF0Zm9ybSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQpKYXBhbiBpc3Qgd29obCBkZXIgZ3LDtsOfdGUgQXVzcmVpw59lciBkZXIgZHJlaSBSZWdpb25lbi4gSGllciBmw7xocnQgZGVyIE5pbnRlbmRvIERTICgxNzUuNTcpIGRpZSBMaXN0ZSBhbi4gQXVjaCBkZXIgQWJzdGFuZCBhdWYgUGxhdHogMiBpc3QgaGllciBncsO2w59lciBhbHMgaW4gZGVuIGFuZGVyZW4gUmVnaW9uZW4gd2VsY2hlciBuaWNodCB2b24gZGVyIFBsYXlzdGF0aW9uIDIgKFBsYXR6IDMpIHNvbmRlcm4gZGVyIFBsYXlzdGF0aW9uIDEgYmVsZWd0IHdpcmQuIFdlaXQgYWJnZXNjaGxhZ2VuIGlzdCBkaWUgUFMyICgxMzkuMiBtaW8pIHZvbiBkZXIgUFMxKDEzOS44MikgamVkb2NoIG5pY2h0LiBTb255cyBiZWlkZSBLb25zb2xlbiBzaW5kIGF1Y2ggZGllIGVpbnppZ2VuIG5pY2h0IE5pbnRlbmRvIGtvbnNvbGVuIGluIGRlbiBUb3AgNy4gQWxsZWdlbWVpbiBpc3QgaGllciBlaW4gZ3Jvw59lciBGb2t1cyBhdWYgSmFwYW5pc2NoZSB1bnRlcm5laG1lbiB6dSBlcmtlbm5lbiB3ZW5uIG1hbiBiZWRlbmt0IGRhcyBkaWUgZXJzdGUsIG5pY2h0IGphcGFuaXNjaGUga29uc29sZSwgZGllIFhib3ggMzYwICgxMi40MykgYXVmIFBsYXR6IDE3IGlzdC4gSmFwYW5pc2NoZSBoZXJzdGVsbGVyIHNpbmQgaW4gZGVyIFNwaWVsZWluZHVzdHJpZSB3ZWl0IHZlcmJyZWl0ZXQgZWluIHNvIGV4dHJlbWVzIFZlcmjDpGx0bmlzIGlzdCBHbG9iYWwgamVkb2NoIG5pY2h0IGRpZSBOb3JtLiBTY2hhdWVuIHdpciB1bnMgZGFzIGdhbnplIGVpbm1hbCBnZW5hdWVyIGFscyBLcmVpc2RpYWdyYW1tZSBhbiB1bSBkaWUgVmVyaMOkbHRuaXNlIGV0d2FzIGRldXRsaWNoZXIgenUgbWFjaGVuLg0KDQojIyMgS3JlaXNkaWFncmFtbWUgey50YWJzZXR9DQoNCkRhIHdpciBiaXNoZXIgbm9jaCBrZWluZSBLcmVpc2RpYWdyYW1tZSBnZW51dHp0IGhhYmVuIHNjaGF1ZW4gd2lyIHVucyBlcnN0IG1hbCBkaWUgVW50ZXJzY2hpZWRlIGluIGRlciBEaWFncmFtbWVyc3RlbGx1bmcgYW4gYmV2b3Igd2lyIHVucyBhdWYgZGllIEFuYWx5c2UgZWJlbmplbmVyIERpYWdyYW1tZSBzdMO8cnplbi4gRGVyIGVpbmZhY2hoZWl0IGhhbGJlciBzY2hhdWVuIHdpciB1bnMgZGFzIGdhbnplIG51ciBhbSBCZWlzcGllbCBFdXJvcGEgYW4sIGRpZSBhbmRlcmVuIERpYWdyYW1tZSB1bnRlcnNjaGVpZGVuIHNpY2ggYWJlciBudXIgaW4gZGVtIFdlcnQgaW4gZGVyICpzdW1tYXJpemUqIGZ1bmt0aW9uIHNvd2llIGRlbiBBY2hzZW4tIHVuZCBkZXIgRGlhZ3JiZXNjaHJpZnR1bmcuIERlciBHcnVuZGF1ZmJhdSBkZXIgRGlhZ3JhbW0gZXJzdGVsbHVuZyBpc3QgaGllciB3aWVkZXIgw6RobmxpY2ggd2llIGJlaSBkZW4gUGFyZXRvZGlhZ3JhbW1lbi4gWnVlcnN0IGdydXBwaWVyZW4gd2lyIGRpZSBEYXRlbiwgc29ydGllcmVuIHNpZSBuYWNoIEFuemFobCBkZXIgVmVya8OkdWZlIHVuZCBlcnN0ZWxsZW4gdW5zZXJlIEFjaHNlbmJlc2NocmlmdHVuZ2VuLiBEYW5hY2ggenVtIGludGVyZXNzYW50ZW4gVGVpbCBkZXIgRGlhZ3JhbW1lcnN0ZWxsdW5nIHdlbGNoZXIgc2ljaCBlaWdlbnRsaWNoIGF1Y2ggbmljaHQgZ3Jvw58gdm9uIGRlbiBQYXJldG9kaWFncmFtbWVuIHVudGVyc2NoZWlkZXQuIFdpciDDvGJlcmdlYmVuIHVuc2VyZSBTb3J0aWVydGVuIERhdGVuIGFuICpQbG90X2x5KCkqIHVuZCB2ZXJ3ZW5kZW4gZGllIEZ1bmt0aW9uICphZGRfcGllKiBtaXQgZW50c3ByZWNoZW5kZW4gUGFyYW1ldGVybiB6dXIgRGlhZ3JhbW0gZXJzdGVsbHVuZy4gRGllc2UgdW50ZXJzY2hlaWRlbiBzaWNoIGV0d2FzIHZvbiBkZW4gUGFyZXRvZGlhZ3JhbW1lbi4gKlZhbHVlcyogc2luZCBoaWVyYmVpIGRpZSBXZXJ0ZSwgZGllIGRpZSBHcsO2w59lIHVuZCAqbGFiZWxzKiBkaWUgQmV6ZWljaG51bmcgZGVyICJLdWNoZW5zdMO8Y2tlIiBmZXN0bGVnZW4uIERlciBsZXR6dGUgaW50ZXJlc3NhbnRlIFBhcmFtZXRlciBpc3QgKnRleHRpbmZvKiBtaXQgd2VsY2hlbSBGZXN0Z2VsZWd0IHdpcmQgd2FzIGFscyB0ZXh0IGluIGRlbiBBYnNjaG5pdHRlbiBhdWZnZWbDvGhydCB3aXJkLiBJbiB1bnNlcmVtIEJlaXNwaWVsIG51dHplbiB3aXIgaGllciAqdGV4dGluZm89J2xhYmVsK3BlcmNlbnQnKiB1bWQgc293b2hsIGRpZSBCZXplaWNobnVuZ2VuIGFscyBhdWNoIGRlbiBHZW5hdWVuIFByb3plbnR3ZXJ0IGFuenV6ZWlnZW4uDQoNCiMjIyMgRXVyb3BhDQoNCmBgYHtyIHBsb3QoUGxhdGZvcm1SYW5raW5nX0VVMiksIGVjaG8gPSBUUlVFLG1lc3NhZ2U9RkFMU0UscmVzdWx0cz0nbWFya3VwJyx9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUGxhdGZvcm0pICU+JSANCiAgc3VtbWFyaXplKHN1bShFVV9TYWxlcykpICAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEVVX1NhbGVzKSINCiAgICApDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQbGF0Zm9ybSA8LSBhc19mYWN0b3Iob3JkZXJlZCRQbGF0Zm9ybSkNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQbGF0Zm9ybSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiRVUgdmVya8OkdWZlIChpbiBtaW8pIg0KDQopDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX3BpZSh2YWx1ZXMgPX5HbG9iYWxfU2FsZXMsbGFiZWxzPX5QbGF0Zm9ybSx0ZXh0aW5mbz0nbGFiZWwrcGVyY2VudCcsICB0ZXh0cG9zaXRpb24gPSAnaW5zaWRlJywNCiAgICAgICAgICAgbmFtZT0iRVUgVmVya2F1ZnN6YWhsZW4gcHJvIFBsYXRmb3JtIiAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iRVUgVmVya2F1ZnN6YWhsZW4gcHJvIFBsYXRmb3JtIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5LA0KICAgICAgICAgc2hvd2xlZ2VuZCA9IEZBTFNFLA0KICAgICAgICAgYXV0b3NpemUgPSBGDQogICAgICAgICApDQpgYGANCk9obmUgZGlyZWt0ZSBHbG9iYWxlIHZlcmdsZWljaHNkaWFncmFtbWUga8O2bm5lbiB3aXIgaGllciBpbSBlcnN0ZW4gU2Nocml0dCBub2NoIGtlaW5lIGdyb8OfYXJ0aWdlbiBBdXNzYWdlbiB0cmVmZmVuIHdlcmRlbiBhYmVyIGltIHNww6R0ZXJlbiBWZXJsYXVmIGF1ZiBkaWVzZSBlaW5nZWhlbi4gV2FzIHdpciBoaWVyIGFsbGVyZGluZ3MgZ3V0IGVya2VubmVuIEvDtm5uZW4gaXN0LCBkYXNzIGRpZSBncsO2w590ZW4gdmllciBQbGF0Zm9ybWVuIGhpZXIgNTAuNSUgZGVyIEdlc2FtdHZlcmvDpHVmZSBhdXNtYWNoZW4gdW5kIFNvbnlzIEtvbnNvbGVuIHNvZ2FyIDI4JS4NCg0KIyMjIyBOb3JkLUFtZXJpa2ENCmBgYHtyIHBsb3QoUGxhdGZvcm1SYW5raW5nX05BMiksIGVjaG8gPSBUUlVFLG1lc3NhZ2U9RkFMU0UscmVzdWx0cz0nbWFya3VwJyx9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUGxhdGZvcm0pICU+JSANCiAgc3VtbWFyaXplKHN1bShOQV9TYWxlcykpICAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKE5BX1NhbGVzKSINCiAgICApDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQbGF0Zm9ybSA8LSBhc19mYWN0b3Iob3JkZXJlZCRQbGF0Zm9ybSkNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQbGF0Zm9ybSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiTkEgdmVya8OkdWZlIChpbiBtaW8pIg0KDQopDQoNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfcGllKHZhbHVlcyA9fkdsb2JhbF9TYWxlcyxsYWJlbHM9flBsYXRmb3JtLHRleHRpbmZvPSdsYWJlbCtwZXJjZW50JywgdGV4dHBvc2l0aW9uID0gJ2luc2lkZScsDQogICAgICAgICAgIG5hbWU9Ik5BIFZlcmthdWZzemFobGVuIHBybyBQbGF0Zm9ybSIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9Ik5BIFZlcmthdWZzemFobGVuIHBybyBQbGF0Zm9ybSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheSwNCiAgICAgICAgIHNob3dsZWdlbmQgPSBGQUxTRSwNCiAgICAgICAgIGF1dG9zaXplID0gRg0KICAgICAgICAgKQ0KYGBgDQpCZWltIGJldHJhY2h0ZW4gZGVzIERpYWdyYW1tZXMgZsO8ciBBbWVyaWthIHNlaGVuIHdpciBkYXMgZGllIFRvcCA0LCB3ZWxjaGUgd2VpdGVyaGluIGF1cyBYYm9YMzYwIFdpaSBQczIgdW5kIFBTMyBiZXN0ZWhlbiwgbnVyIG5vY2ggNDcuNTMlIGF1c21hY2hlbi4gR3LDtsOfdGVyIFZlcmxpZXJlciBzaW5kIGhpZXIgU29ueXMgS29uc29sZW4sIHdlbGNoZSBudXIgbm9jaCAyMi4yMyUgYXVzbWFjaGVuLg0KDQojIyMjIEphcGFuDQoNCmBgYHtyIHBsb3QoUGxhdGZvcm1SYW5raW5nX0pQMiksIGVjaG8gPSBUUlVFLG1lc3NhZ2U9RkFMU0UscmVzdWx0cz0nbWFya3VwJyx9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUGxhdGZvcm0pICU+JSANCiAgc3VtbWFyaXplKHN1bShKUF9TYWxlcykpICAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEpQX1NhbGVzKSINCiAgICApDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQbGF0Zm9ybSA8LSBhc19mYWN0b3Iob3JkZXJlZCRQbGF0Zm9ybSkNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQbGF0Zm9ybSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiSlAgdmVya8OkdWZlIChpbiBtaW8pIg0KDQopDQoNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfcGllKHZhbHVlcyA9fkdsb2JhbF9TYWxlcyxsYWJlbHM9flBsYXRmb3JtLHRleHRpbmZvPSdsYWJlbCtwZXJjZW50JywgdGV4dHBvc2l0aW9uID0gJ2luc2lkZScsDQogICAgICAgICAgIG5hbWU9IkpQIFZlcmthdWZzemFobGVuIHBybyBQbGF0Zm9ybSIgLCAgcm90YXRpb24gPSA0MCwgY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iSlAgVmVya2F1ZnN6YWhsZW4gcHJvIFBsYXRmb3JtIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5LA0KICAgICAgICAgc2hvd2xlZ2VuZCA9IEZBTFNFLA0KICAgICAgICAgYXV0b3NpemUgPSBGDQogICAgICAgICANCiAgICAgICAgICkNCmBgYA0KSW4gSmFwYW4gbWFjaGVuIGRpZSBUb3AgNCA0NC4yMyUgYXVzIGJlc3RlaGVuIGFiZXIgYmlzIGF1ZiBkaWUgUFMyIGF1cyBnw6RuemxpY2ggYW5kZXJlbiBLb25zb2xlbi4gRGEgU29ueXMgUFMzIHZvbiBkZXIgUFMgZXJzZXR6dCB3aXJkIGhhbHRlbiBkaWVzZSB3ZWl0ZXJoaW4gMjEuNiUgZGVyIFRvcCA0LiBOaW50ZW5kbyBob2x0IHNpY2ggaGllciBqZWRvY2ggZGVuIEdyw7bDn3RlbiBBbnRlaWwgbWl0IDIyLjYzJS4gRWluIHZlcmdsZWljaCBkaWVzZXIgV2VydGUgaXN0IGplZG9jaCwgd2llIGJlcmVpdHMgaW0gVm9yc3Bhbm4gZGVyIFBsYXRmb3JtIFJhbmtpbmdzIGVyd8OkaG50IG1pdCBQcm9ibGVtZW4gZ2VoYWZ0LiBHZW5hdWVyZXMgaGllcnp1IHdpZSBiZXJlaXRzIGVyd8OkaG50IGltIFtGYXppdF0oI0F1ZmdldHJldGVuZVByb2JsZW1lKS4NCg0KIyMgey19DQoNCg0KKioqDQoNCiMgUGxhdGZvcm0gVmVya2F1ZnN6YWhsZW4gaW0gbGF1ZmUgZGVyIEphaHJlIHsjU2FsZXNQZXJQbGF0Zm9ybX0NCg0KTmFjaGRlbSB3aXIgdW5zIGRpZSBQbGF0Zm9ybSB2ZXJ0ZWlsdW5nIGFuZ2VzY2hhdXQgaGFiZW4gc3RlbGx0IHNpY2ggZGllIEZyYWdlIG9iIGVzIGltIGxhdWZlIGRlciBKYWhyZSB1bnRlcnNjaGllZGUgaW4gZGVuIFZlcmvDpHVmZW4gZ2lidC4NCg0KDQpVbSB1bnMgZGllcyBhbnp1c2NoYXVuIHZlcndlbmRlbiB3aXIgZWluZSBuZXVlIGFydCBkZXIgR3JhZmlrIGRpZSB3aXIgYmlzaGVyIG5vY2ggbmljaHQgdmVyd2VuZGV0IGhhYmVuLiBadW0gZXJzdGVsbGVuIGRlciBHcmFmaWsgZ3J1cHBpZXJlbiB3aXIgenVlcnN0IHdpZWRlciB1bnNlcmUgRGF0ZW4gdW5kIGFkZGllcmVuIGRpZSB3ZXJ0ZSBkZXIgU2FsZXMgcHJvIEphaHIgdW5kIFBsYXRmb3JtIGF1Zi4gWlVzw6R0emxpY2ggenVtIEZpbHRlciBkZXIgdW5nw7xsdGlnZW4gSmFocmUgZmlsdGVyIHdpciBhbGxlcmRpbmdzIGFsbGUgU3VtbWVuIG1pdCB3ZW5pZ2VyIGFscyA2MCBtaW8gaW4gU2FsZXMuIERpZXMgaXN0IHVtIGVpbmUgw5xiZXJsYWR1bmcgZGVzIERpYWdyYW1tcyB6dSB2ZXJoaW5kZXJuIGbDvGhydCBhYmVyIHp1IGFuZGVyZW4gW1Byb2JsZW1lbl0oI0F1ZmdldHJldGVuZVByb2JsZW1lKS4gTmV1IGluIGRlciBlcnN0ZWxsdW5nIGRpZXNlcyBEaWFncmFtbXMgc2luZCBhdWNoIGRpZSBiZWZlaGxlICphcnJhbmdlKCkqIHVuZCAqc2xpY2UoKSouIEFycmFuZ2Ugc29ydGllcnQgZGllIFRhYmVsbGUgYW5oYW5kIGRlciBnZWdlYmVuZW4gU3BhbHRlIGluIHVuc2VyZW0gZmFsbCBpc3QgZGFzIGRpZSBTdW1tZSBkZXIgR2xvYmFsZW4gdmVya8OkdWZlLiBTbGljZSBlbnRmZXJudCBhbGxlIFNwYWx0ZW4gYmlzIGF1ZiBqZW5lLCB3ZWxjaGUgd2lyIHZlcndlbmRlbiB3b2xsZW4uIE5ldSBiZWkgZGVyIERpYWdhbW0gZXJzdGVsbHVuZyBzaW5kIGhpZXIgZGllIFBhcmFtZXRlciAqbW9kZSA9ICdub25lJyogc293aWUgKnN0YWNrZ3JvdXAgPSAnb25lJyogd2VsY2hlIGRpZSBoaWVyIHp1IHNlaGVuZGUgR3JhZmlrIGVyemV1Z2VuLg0KYGBge3IgcGxvdChTYWxlc1BlclBsYXRmb3JtYnlZZWFyKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoWWVhciwgUGxhdGZvcm0pICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKGdyX3N1bSA9IHN1bShHbG9iYWxfU2FsZXMpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgICU+JSBmaWx0ZXIoZ3Jfc3VtPjYwKSU+JQ0KICBhcy5kYXRhLmZyYW1lKCkNCmdyb3VwZWQgPC0gZ3JvdXBlZCAlPiVhcnJhbmdlKGRlc2MoZ3Jfc3VtKSkgJT4lIA0KICBncm91cF9ieShZZWFyLCBQbGF0Zm9ybSkgJT4lDQogIHNsaWNlKDE6MykNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsUGxhdGZvcm0sZ3Jfc3VtKQ0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiSmFociINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAidmVya8OkdWZlIHBybyBQbGF0Zm9ybSAoaW4gbWlvKSINCg0KKQ0KDQoNCmZpbHRlcmVkICU+JQ0KcGxvdF9seSh4ID0gflllYXIsIHkgPSB+Z3Jfc3VtLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ25vbmUnLCBzdGFja2dyb3VwID0gJ29uZScsY29sb3IgPSB+UGxhdGZvcm0gLGNvbG9ycyA9IG15UGFsZXR0ZSklPiUgDQogIGxheW91dCh0aXRsZT0iVmVya8OkdWZlIHBybyBQbGF0Zm9ybSB2b24gMTk4MC0yMDE2IiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCmBgYA0KSW0gZXJzdGVuIE1vbWVudCBpc3QgZGllIEdyYWZpayBzZWhyIHZlcndpcnJlbmQgYWJlciBkcsO2c2VsbiB3aXIgZGFzIGdhbnplIGVpbm1hbCBnZW5hdWVyIGF1Zi4gWnVlcnN0IGVpbm1hbCBmw6RsbHQgYXVmLCBkYXNzIGRpZSBKYWhyZSAxOTgwLTE5ODggc293aWUgMTk5MC0xMDA1IHVuZCAyMDE2IGZlaGxlbi4gRGllcyBsaWVndCBhbiBkZW4gb2JlbiBnZXfDpGhsdGVuIEZpbHRlcm4gdW5kIGRlbiBpbiBkZW4gSmFocmVuIHBybyBQbGF0dGZvcm0gZ2VtZXNzZW4genUgZ2VyaW5nZW4gVmVya2F1ZnN6YWhsZW4uIFp3aXNjaGVuIGRlbiBKYWhyZW4gMTk5NiB1bmQgMjAwMCBpc3QgaGllciBudXIgZGllIFBsYXlzdGF0aW9uLCB3ZWxjaGUgMTk5NCB2ZXLDtmZmZW50bGljaHQgd3VyZGUgenUgZXJrZW5uZW4uIEltIEphaHJlIDIwMDAgd2lyZCBkaWVzZSBkYW5uIHZvbiBkZXIgUGxheXN0YXRpb24gMiwgd2VsY2hlIGFtIDA0LjAzLjIwMDAgcmVsZWFzdCB3dXJkZSBhYmdlbMO2c3QuIEF1Y2ggZGVyIEdhbWVib3kgQWR2YW5jZWQgaGllciBpbiBkZW4gSmFocmVuIDIwMDAtMjAwMyBzb3dpZSAyMDA0IHp1IGVya2VubmVuLCBvYndvaGwgZGllc2VyIEdsb2JhbCBlcnN0IE1pdHRlIGRlcyBKYWhyZXMgMjAwMSByZWxlYXN0IHd1cmRlLjIwMDQgd2lyZCBkaWUgUGxheXN0YXRpb24gMiBkYW5uIHZvbiBkZXIgWGJveCwgd2VsY2hlIGFtIDIyLjAyLjIwMDIgZXJzdG1hbHMgdmVyw7ZmZmVudGxpY2ggd3VyZGUsIGt1cnp6ZWl0aWcgYWJnZWzDtnN0IGJldm9yIGRpZSBXaWkoMDIuMTIuMjAwNikgbWl0IG51ciBlaW5lbSBWZXJrYXVmc21vbmF0IGRlcyBKYWhyZXMgMjAwNiBkaWUgRsO8aHJ1bmcgw7xiZXJuaW1tdC4gQXVjaCBkaWUgVmVya2F1ZnN6YWhsZW4gZGVzIE5pbnRlbmRvIERTICgwMi4xMi4yMDA0KSBzaW5kIGluIGRlbiBKYWhyZW4gMjAwNS0yMDEwIGd1dCBlcmtlbm5iYXIuIERpZSBYYm9YMzYwICgxMC4xMi4yMDA1KSDDvGJlcm5pbW10IGFiIDIwMDcgZGVuIGVyc3RlbiBQbGF0eiBkZXIgUmFuZ2xpc3RlIHVuZCB3aXJkIGVyc3QgMjAxNCB2b24gZGVyIFBTNCgxNS4xMS4yMDEzKSBhYmdlbMO2c3QuIA0KDQoNCkFsbGdlbWVpbiBpc3QgaGllciBlaW4gVHJlbmQgZXJrZW5uYmFyLiBNZWlzdCB2ZXJrYXVmZW4gUGxhdGZvcm1lbiB3aWUgenUgZXJ3YXJ0ZW4gZWluaWdlIFplaXQgbmFjaCBSZWxlYXNlIGRpZSBtZWlzdGVuIFNwaWVsZS4gRXJzdGF1bmxpY2hlcndlaXNlIGlzdCBkaWVzIGplZG9jaCBuaWNodCBrdXJ6IG5hY2ggUmVsZWFzZSBzb25kZXJuIHouVC4gZXJzdCBlaW5pZ2UgSmFocmUgc3DDpHRlci4gSW50ZXJlc3NhbnQgd8OkaHJlIGhpZXIgZWluZSBkZXRhaWxsaWVydGVyZSBhbmFseXNlIGFiZXIgd2VpdGVyZXMgZGF6dSBbaGllcl0oI0F1c2JsaWNrSW5EaWVadWt1bmZ0KS4NCg0KDQoNCioqKg0KDQojIFB1Ymxpc2hlciBWZXJnbGVpY2ggeyNQdWJsaXNoZXJSZWxlYXNlc30NCg0KTmFjaGRlbSB3aXIgdW5zIG51biBlaW5lIMOcYmVyc2ljaHQgw7xiZXIgZGllIFBsYXRmb3JtZW4gZ2VtYWNodCBoYWJlbiB3w6RyZSBlcyBkb2NoIGludGVyZXNzYW50IHp1IHdpc3NlbiBvYiBzaWNoIG5lYmVuIGJlc3RpbW10ZW4gUGxhdGZvcm1lbiBhdWNoIGJlc3RpbW10ZSBFbnR3aWNrbGVyL1B1Ymxpc2hlciBow6R1ZmVuLiBBbnp1bmVobWVuIGlzdCBoaWVyYmVpIGRhcyBOYW1lbmhhZnRlIFB1Ymxpc2hlciB3aWUgRUEgdW5kIE5pbnRlbmRvIGRpZSBMaXN0ZSBhbmbDvGhyZW4uIEhpZXJ6dSB2ZXJ3ZW5kZW4gd2lyIHdpZWRlcnVtIFBhcmV0b2RpYWdyYW1tZS4gRWluZSBnZW5hdWVyZSBlcmtsw6RydW5nIHp1ciBlcnN0ZWxsdW5nIGViZW5qZW5lciBnaWJ0IGVzIFtoaWVyXSgjUGxhdGZvcm1hbmFseXNlKS4gRWluemlnZSBuZXVlcnVuZyBpbiBkaWVzZW0gYWJzY2huaXR0IGlzdCBkYXMgS8O8cnplbiBkZXIgTmFtZW4gdW0gZGllIEJlZ3JpZmZlICJFbnRlcnRhaW5tZW50IiwgIkludGVyYWN0aXZlIiwgIkdhbWUiLCAiR2FtZXMiIHVuZCAiU3R1ZGlvcyIgZGEgZGllcyBkaWUgTmFtZW4gbnVyIHVubsO2dGlnIHZlcmzDpG5nZXJ0LiBVbSBkaWVzIHp1IGVycmVpY2hlbiBtdXR6ZW4gd2lyIGRpZSBGdW5rdGlvbiAqc3RyX3JlbW92ZV9hbGwoKSogYXVmIGRpZSBTcGFsdGUgUHVibGlzaGVyLiANCg0KIyMgUHVibGlzaGVyIHsudGFic2V0fQ0KDQojIyMgbmFjaCBBbnphaGwNCmBgYHtyIHBsb3QyLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoQW56YWhsID1uKCkpICU+JSAgDQogIGZpbHRlcihBbnphaGw+MTAwKSAlPiUgZmlsdGVyKFB1Ymxpc2hlciE9IlVua25vd24iKQ0KDQoNCg0KDQpQdWJsaXNoZXJTYWxlcyA8LSB2Z3NhbGVzICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkgJT4lIGZpbHRlcihHbG9iYWxfU2FsZXM+MzAwKQ0KDQoNCg0KZ3JvdXBlZCA8LSBncm91cGVkICAlPiUgZmlsdGVyKFB1Ymxpc2hlciAlaW4lIFB1Ymxpc2hlclNhbGVzJFB1Ymxpc2hlcikNCg0KDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRBbnphaGwpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiRW50ZXJ0YWlubWVudCIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiSW50ZXJhY3RpdmUiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIlN0dWRpb3MiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkdhbWVzIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFB1Ymxpc2hlcikNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQdWJsaXNoZXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkFuemFobCINCikNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoUHVibGlzaGVyLEFuemFobCwgLmRlc2M9InRydWUiKSwNCiAgICAgICAgICAgeT1+QW56YWhsLA0KICAgICAgICAgICBuYW1lPSJTcGllbGUgQW56YWhsIHBybyBQdWJsaXNoZXIiDQogICAgICAgICAgICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJTcGllbGUgQW56YWhsIHBybyBQdWJsaXNoZXIiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgIA0KICAgICAgICAgKQ0KYGBgDQoNCkJldHJhY2h0ZW4gd2lyIHp1ZXJzdCBlaW5tYWwgZGllIEFuemFobCBkZXIgU3BpZWxlcmVsZWFzZXMuIFdlbmlnIMO8YmVyYXNjaGVuZCBpc3QgaGllciBFQSAoMTM1MSksIG1pdCBqw6RocmxpY2ggdmVyw7ZmZmVudGxpY2hlbmRlbiBuYW1lbmhhZnRlbiBTcGllbGVuIHdpZSBGSUZBIHVuZCBNYWRkZW4gTkZMIHNvd2llIGFuZGVyZW4gYmVrYW5udGVuIFJlaWhlbiB3aWUgTmVlZCBmb3IgU3BlZWQsIEJhdHRsZWZpZWxkIG9kZXIgU2ltcywgYW5mw7xocmVyIGRlciBMaXN0ZS4gQW4gendlaXRlciBzdGVsbGUgYmVmaW5kZXQgc2ljaCBBY3RpdmlzaW9uICg5NzUpIGRpZSB1bnRlciBhbmRlcmVtIFNwaWVsZSB3aWUgV29ybGQgb2YgV2FyY3JhZnQsIGRpZSBEaWFibG8gcmVpaGUgc293aWUgQ2FuZHkgQ3J1c2ggZW50d2lja2VsdGVuLiBadW0gWmVpdHB1bmt0IGRlciBFcnN0ZWxsdW5nIGRpZXNlciBBcmJlaXQgc2luZCBkaWVzZSBub2NoIGVpbiBlaWdlbmVyIEtvbnplcm4gd2VyZGVuIGFsbGVyZGluZ3Mgdm9yYXVzaWNodGxpY2ggMjAyMyBUZWlsIHZvbiBNaWNyb3NvZnQuIERhcmF1ZiBmb2xnZW4gaW4ga3VyemVuIGFic3TDpG5kZW4gVWJpc29mdCAoOTIxKSwgd2VsY2hlIGbDvHIgQXNzYXNpbnMgQ3JlZWQsIFJhaW5ib3ggc2l4IG9kZXIgQW5ubyBiZWthbm50IHNpbmQsIHNvd2llIFRIUSAgbWl0IDcxNSAoR290aGljLCBEYXJrc2lkZXJzLCBUaXRhblF1ZXN0KS4gQXVjaCBOaW50ZW5kbyAoNzAzKSBtaXQgTWFyaW8sIFBva2Vtb24gdW5kIFplbGRhIHNvd2llIFNvbnkgKDYzOCksIGJla2FubnQgZHVyY2ggZGllIEdyYW4gVG91cmlzbW8gdW5kIFVuY2hhcnRlZCBSZWloZSBzb3dpZSBUaGUgbGFzdCBvZiBVcywgc2luZCBuaWNodCB3ZWl0IGFiZ2VzY2hsYWdlbi4gRGVuIGxldHp0ZW4gcGxhdHogZGVyIFRvcCBQdWJsaXNoZXIgYmVsZWd0IFRha2UgVHdvLCB3ZWxjaGUgZsO8ciBHVEEsIEJvcmRlcmxhbmRzIHVuZCBDaXZpbGl6YXRpb24gYmVrYW5udCBzaW5kLCBtaXQgNDEzLg0KDQojIyMgbmFjaCBWZXJrYXVmc3phaGxlbg0KYGBge3IgcGxvdChQdWJsaXNoZXJSYW5raW5nX0dsb2JhbCksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShBbnphaGwgPW4oKSxzdW0oR2xvYmFsX1NhbGVzKSkgJT4lDQogIGZpbHRlcihBbnphaGw+MTAwKSAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEdsb2JhbF9TYWxlcykiDQogICAgKQ0KDQpQdWJsaXNoZXJTYWxlcyA8LSB2Z3NhbGVzICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkgJT4lIGZpbHRlcihHbG9iYWxfU2FsZXM+MzAwKQ0KDQoNCg0KZ3JvdXBlZCA8LSBncm91cGVkICAlPiUgZmlsdGVyKFB1Ymxpc2hlciAlaW4lIFB1Ymxpc2hlclNhbGVzJFB1Ymxpc2hlcikNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiRW50ZXJ0YWlubWVudCIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiSW50ZXJhY3RpdmUiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIlN0dWRpb3MiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkdhbWVzIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFB1Ymxpc2hlcikNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQdWJsaXNoZXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlZlcmvDpHVmZSAoaW4gbWlvKSINCg0KKQ0KDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoUHVibGlzaGVyLEdsb2JhbF9TYWxlcywgLmRlc2M9InRydWUiKSwNCiAgICAgICAgICAgeT1+R2xvYmFsX1NhbGVzLA0KICAgICAgICAgICBuYW1lPSJWZXJrYXVmc3phaGxlbiBwcm8gUHVibGlzaGVyIg0KICAgICAgICAgICAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iVmVya2F1ZnN6YWhsZW4gcHJvIFB1Ymxpc2hlciIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQpCZWltIEJldHJhY2h0ZW4gZGVyIFZlcmthdWZzemFobGVuIGbDpGxsdCBoaWVyIGRpcmVrdCBkaWUgZGlza3JlcGFueiB6d2lzY2hlbiBBbnphaGwgZGVyIFNwaWVsZXJlbGVhc2VzIHVuZCBBbnphaGwgZGVyIFNwaWVsZXZlcmvDpHVmZSBhdWYuIEltIGdlZ2Vuc2F0eiB6dSBkZXIgQW56YWhsIGRlciBTcGllbGUgKGJlaSBkZW0gTmludGVuZG8gbnVyIGF1ZiBwbGF0eiA2IFNpdHopIGRvbWluaWVydCBOaW50ZW5kbygxLjc4NiBtcmQpIGluIFNhbGVzLiBFQSAoMS4xIG1yZCksIHdlbGNoZSBub2NoIG1pdCBBYnN0YW5kIGRpZSBtZWlzdGVuIHNwaWVscmVsZWFzZXMgaGF0dGVuIHNpbmQgaW4gZGVuIFZlcmvDpHVmZW4gbnVyIG5vY2ggbWl0IGRldXRsaWNoZW0gQWJzdGFuZCBhdWYgUGxhdHogMi4gQXVjaCBkaWUgYW5kZXJlbiBQbMOkdHplIHZlcsOkbmRlcm4gc2ljaCBsZWljaHQgZGllIFVudGVyc2NoaWVkZSBzaW5kIGhpZXIgamVkb2NoIGRldXRsaWNoIGdlcmluZ2VyIGFscyBiZWkgTmludGVuZG8gdW5kIEVBLiBJbnRlcmVzc2FudCB3w6RyZSBoaWVyenUgdmllbGxlaWNodCBub2NoIGVpbiBkaXJla3RlciB2ZXJnbGVpY2ggendpc2NoZW4gQW56YWhsIHVuZCBTYWxlcyBhYmVyIGdlbmF1ZXJlcyBkYXp1IGltIFtGYXppdF0oI0F1c2JsaWNrSW5EaWVadWt1bmZ0KQ0KDQojIyB7LX0NCg0KDQoNCioqKg0KDQojIFB1Ymxpc2hlciBSYW5raW5nIG5hY2ggUmVnaW9uIHsjUHVibGlzaGVyUmFua2luZ2J5UmVnaW9ufQ0KDQpOYWNoZGVtIHdpciB1bnMgZWluZW4gQWxsZ2VtZWluZW4gw5xiZXJibGljayDDvGJlciBkaWUgUHVibGlzaGVyIGdlbWFjaHQgaGFiZW4gYmV0cmFjaHRlbiB3aXIgZGllIFJlZ2lvbmFsZW4gdW50ZXJzY2hpZWRlIGluIGRlbiBWZXJrYXVmc3phaGxlbi4gSGllcnp1IHZlcndlbmRlbiB3aXIgZXJuZXV0IGRpZSBCZXJlaXRzIGJla2FubnRlbiBTaGVtYXRhIGRlciBbUGFyZXRvLV0oI1BsYXRmb3JtYW5hbHlzZSkgdW5kIFtLcmVpc2RpYWdyYW1tXSgjUGxhdGZvcm1SYW5raW5nQnlSZWdpb24pIGtvbWJvLiBFaW5lbiBSZWZyZXNoZXIgZsO8ciBkaWUgRXJzdGVsbHVuZyBlYmVuamVuZXIgRGlhZ3JhbW1lIGdpYnQgZXMgdmlhIGRlbiBFbnRzcHJlY2hlbmRlbiBMaW5rcy4NCg0KIyMgUmFua2luZyBuYWNoIFJlZ2lvbiB7LnRhYnNldH0NCiMjIyBCYWxrZW5kaWFncmFtbWUgey50YWJzZXR9DQojIyMjIEV1cm9wYQ0KDQpgYGB7ciBwbG90KFB1Ymxpc2hlclJhbmtpbmdfRVUxKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIpICU+JSANCiAgc3VtbWFyaXplKEFuemFobCA9bigpLHN1bShFVV9TYWxlcykpICU+JQ0KICBmaWx0ZXIoQW56YWhsPjEwMCkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShFVV9TYWxlcykiDQogICAgKQ0KDQpQdWJsaXNoZXJTYWxlcyA8LSB2Z3NhbGVzICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkgJT4lIGZpbHRlcihHbG9iYWxfU2FsZXM+MzAwKQ0KDQoNCg0KZ3JvdXBlZCA8LSBncm91cGVkICAlPiUgZmlsdGVyKFB1Ymxpc2hlciAlaW4lIFB1Ymxpc2hlclNhbGVzJFB1Ymxpc2hlcikNCg0KDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkVudGVydGFpbm1lbnQiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkludGVyYWN0aXZlIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJTdHVkaW9zIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lcyIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiR2FtZSIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LSBhc19mYWN0b3Iob3JkZXJlZCRQdWJsaXNoZXIpDQoNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiUHVibGlzaGVyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJFVSB2ZXJrw6R1ZmUgKGluIG1pbykiDQoNCikNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfYmFycyh4PX5mY3RfcmVvcmRlcihQdWJsaXNoZXIsR2xvYmFsX1NhbGVzLCAuZGVzYz0idHJ1ZSIpLA0KICAgICAgICAgICB5PX5HbG9iYWxfU2FsZXMsDQogICAgICAgICAgIG5hbWU9IkVVIFZlcmthdWZzemFobGVuIHBybyBQdWJsaXNoZXIiDQogICAgICAgICAgICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJFVSBWZXJrYXVmc3phaGxlbiBwcm8gUHVibGlzaGVyIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCg0KSW0gdmVyZ2xlaWNoIHp1IGRlbiBHbG9iYWxlbiBWZXJrYXVmc3phaGxlbiBmw6RsbHQgaGllciBhdWYgZGFzIEVBICgzNzEuMjcgbWlvKSBkZXV0bGljaCBkaWNodGVyIGhpbnRlciBOaW50ZW5kbyg0MTguNzQpIGF1ZiBkZW0gWndlaXRlbiBQbGF0eiBpc3QuIERlciBBYnN0YW5kIHp3aXNjaGVuIEVBIHVuZCBBY3RpdmlzaW9uICgyMTUuNTMpIGlzdCBkZW1lbnRzcHJlY2hlbmQgYXVjaCBkZXV0bGljaCBncsO2w59lci4gRGllIHJlc3RsaWNoZW4gd2VydGUgdW50ZXJzY2hlaWRlbiBzaWNoIGFiZXIga2F1bS4NCg0KIyMjIyBOb3JkIEFtZXJpa2ENCmBgYHtyIHBsb3QoUHVibGlzaGVyUmFua2luZ19OQTEpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoQW56YWhsID1uKCksc3VtKE5BX1NhbGVzKSkgJT4lDQogIGZpbHRlcihBbnphaGw+MTAwKSAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKE5BX1NhbGVzKSINCiAgICApDQoNClB1Ymxpc2hlclNhbGVzIDwtIHZnc2FsZXMgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIpICU+JSANCiAgc3VtbWFyaXplKHN1bShHbG9iYWxfU2FsZXMpKSAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEdsb2JhbF9TYWxlcykiDQogICAgKSAlPiUgZmlsdGVyKEdsb2JhbF9TYWxlcz4zMDApDQoNCg0KDQpncm91cGVkIDwtIGdyb3VwZWQgICU+JSBmaWx0ZXIoUHVibGlzaGVyICVpbiUgUHVibGlzaGVyU2FsZXMkUHVibGlzaGVyKQ0KDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkVudGVydGFpbm1lbnQiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkludGVyYWN0aXZlIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJTdHVkaW9zIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lcyIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiR2FtZSIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LSBhc19mYWN0b3Iob3JkZXJlZCRQdWJsaXNoZXIpDQoNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiUHVibGlzaGVyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJOQSB2ZXJrw6R1ZmUgKGluIG1pbykiDQoNCikNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfYmFycyh4PX5mY3RfcmVvcmRlcihQdWJsaXNoZXIsR2xvYmFsX1NhbGVzLCAuZGVzYz0idHJ1ZSIpLA0KICAgICAgICAgICB5PX5HbG9iYWxfU2FsZXMsDQogICAgICAgICAgIG5hbWU9Ik5BIFZlcmthdWZzemFobGVuIHBybyBQdWJsaXNoZXIiDQogICAgICAgICAgICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJOQSBWZXJrYXVmc3phaGxlbiBwcm8gUHVibGlzaGVyIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCg0KQXVjaCBpbiBOb3JkIEFtZXJpa2Ega2FubiBFQSg1OTUuMDcpIGxlaWNodCBncsO2w59lcmUgVmVya2F1ZnN6YWhsZW4gaW0gdmVyZ2xlaWNoIG1pdCBOaW50ZW5kbyAoODE2Ljg3KSBhbHMgbm9jaCBHbG9iYWwgdmVyYnVjaGVuLiBJbSBnZWdlbnNhdHogenUgRXVyb3BhIHNjaGVpbnQgamVkb2NoIEFjdGl2aXNpb24gKDQyOS43KSBpbiBBbWVyaWthIGRldXRsaWNoIGJlbGllYnRlciB6dSBzZWluLiBEaWUgd2VpdGVyZW4gUHVibGlzaGVyIHNpbmQgYXVjaCB3ZWl0ZXJoaW4gbmljaHQgUmVsZXZhbnQuDQoNCiMjIyMgSmFwYW4NCmBgYHtyIHBsb3QoUHVibGlzaGVyUmFua2luZ19KUDEpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoQW56YWhsID1uKCksc3VtKEpQX1NhbGVzKSkgJT4lDQogIGZpbHRlcihBbnphaGw+MTAwKSAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEpQX1NhbGVzKSINCiAgICApDQoNClB1Ymxpc2hlclNhbGVzIDwtIHZnc2FsZXMgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIpICU+JSANCiAgc3VtbWFyaXplKHN1bShHbG9iYWxfU2FsZXMpKSAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEdsb2JhbF9TYWxlcykiDQogICAgKSAlPiUgZmlsdGVyKEdsb2JhbF9TYWxlcz4zMDApDQoNCg0KDQpncm91cGVkIDwtIGdyb3VwZWQgICU+JSBmaWx0ZXIoUHVibGlzaGVyICVpbiUgUHVibGlzaGVyU2FsZXMkUHVibGlzaGVyKQ0KDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkVudGVydGFpbm1lbnQiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkludGVyYWN0aXZlIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJTdHVkaW9zIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lcyIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiR2FtZSIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LSBhc19mYWN0b3Iob3JkZXJlZCRQdWJsaXNoZXIpDQoNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiUHVibGlzaGVyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJKUCB2ZXJrw6R1ZmUgKGluIG1pbykiDQoNCikNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfYmFycyh4PX5mY3RfcmVvcmRlcihQdWJsaXNoZXIsR2xvYmFsX1NhbGVzLCAuZGVzYz0idHJ1ZSIpLA0KICAgICAgICAgICB5PX5HbG9iYWxfU2FsZXMsDQogICAgICAgICAgIG5hbWU9IkpQIFZlcmthdWZzemFobGVuIHBybyBQdWJsaXNoZXIiDQogICAgICAgICAgICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJKUCBWZXJrYXVmc3phaGxlbiBwcm8gUHVibGlzaGVyIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCg0KSmFwYW4gWmVpZ3QgaGllciB3b2hsIGRlbiBEZXV0bGljaHN0ZW4gdW50ZXJzY2hpZWQgYXVmLiBOaW50ZW5kbyAoNDU1LjQyKSBEb21pbmllcnQgaGllciBkaWUgVmVya2F1ZnN6YWhsZW4gbWl0IGRlciBtZWhyIGFscyA2IGZhY2hlbiBtZW5nZSBhbiB2ZXJrw6R1ZmVuIGFscyBTb255ICg3NC4xKSB3ZWxjaGUgc2ljaCBkZW4gMi4gUGxhdHogc2ljaGVybi4gRGllIGFuZGVyZW4gUHVibGlzaGVyIHNpbmQgYWxsZSBmYXN0IGdsZWljaCBpcnJlbGV2YW50IGluIEphcGFuLiANCg0KDQojIyMgS3JlaXNkaWFncmFtbWUgey50YWJzZXR9DQoNCiMjIyMgRXVyb3BhDQoNCmBgYHtyIHBsb3QoUHVibGlzaGVyUmFua2luZ19FVSksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShBbnphaGwgPW4oKSxzdW0oRVVfU2FsZXMpKSAlPiUNCiAgZmlsdGVyKEFuemFobD4xMDApICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oRVVfU2FsZXMpIg0KICAgICkNCg0KUHVibGlzaGVyU2FsZXMgPC0gdmdzYWxlcyAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSBmaWx0ZXIoR2xvYmFsX1NhbGVzPjMwMCkNCg0KDQoNCmdyb3VwZWQgPC0gZ3JvdXBlZCAgJT4lIGZpbHRlcihQdWJsaXNoZXIgJWluJSBQdWJsaXNoZXJTYWxlcyRQdWJsaXNoZXIpDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiRW50ZXJ0YWlubWVudCIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiSW50ZXJhY3RpdmUiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIlN0dWRpb3MiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkdhbWVzIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFB1Ymxpc2hlcikNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQdWJsaXNoZXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkVVIHZlcmvDpHVmZSAoaW4gbWlvKSINCg0KKQ0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9waWUodmFsdWVzID1+R2xvYmFsX1NhbGVzLGxhYmVscz1+UHVibGlzaGVyLA0KICAgICAgICAgICBuYW1lPSJFVSBWZXJrYXVmc3phaGxlbiBwcm8gUHVibGlzaGVyIg0KICAgICAgICAgICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJFVSBWZXJrYXVmc3phaGxlbiBwcm8gUHVibGlzaGVyIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCg0KSW0gdmVyZ2xlaWNoIHp1IGRlbiBHbG9iYWxlbiBWZXJrYXVmc3phaGxlbiBmw6RsbHQgaGllciBhdWYgZGFzIEVBICgyMy43JSkgZGV1dGxpY2ggZGljaHRlciBoaW50ZXIgTmludGVuZG8oMjYuNyUpIGF1ZiBkZW0gWndlaXRlbiBQbGF0eiBpc3QuIERlciBBYnN0YW5kIHp3aXNjaGVuIEVBIHVuZCBBY3RpdmlzaW9uICgxMy43JSkgaXN0IGRlbWVudHNwcmVjaGVuZCBhdWNoIGRldXRsaWNoIGdyw7bDn2VyLiBEaWUgcmVzdGxpY2hlbiB3ZXJ0ZSB1bnRlcnNjaGVpZGVuIHNpY2gga2F1bS4NCg0KIyMjIyBOb3JkLUFtZXJpa2ENCg0KYGBge3IgcGxvdChQdWJsaXNoZXJSYW5raW5nX05BMiksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShBbnphaGwgPW4oKSxzdW0oTkFfU2FsZXMpKSAlPiUNCiAgZmlsdGVyKEFuemFobD4xMDApICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oTkFfU2FsZXMpIg0KICAgICkNCg0KUHVibGlzaGVyU2FsZXMgPC0gdmdzYWxlcyAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSBmaWx0ZXIoR2xvYmFsX1NhbGVzPjMwMCkNCg0KDQoNCmdyb3VwZWQgPC0gZ3JvdXBlZCAgJT4lIGZpbHRlcihQdWJsaXNoZXIgJWluJSBQdWJsaXNoZXJTYWxlcyRQdWJsaXNoZXIpDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiRW50ZXJ0YWlubWVudCIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiSW50ZXJhY3RpdmUiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIlN0dWRpb3MiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkdhbWVzIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFB1Ymxpc2hlcikNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQdWJsaXNoZXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIk5BIHZlcmvDpHVmZSAoaW4gbWlvKSINCg0KKQ0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9waWUodmFsdWVzID1+R2xvYmFsX1NhbGVzLGxhYmVscz1+UHVibGlzaGVyLHRleHRpbmZvPSdsYWJlbCtwZXJjZW50JywNCiAgICAgICAgICAgbmFtZT0iTkEgVmVya2F1ZnN6YWhsZW4gcHJvIFB1Ymxpc2hlciINCiAgICAgICAgICAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iTkEgVmVya2F1ZnN6YWhsZW4gcHJvIFB1Ymxpc2hlciIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQoNCkF1Y2ggaW4gTm9yZCBBbWVyaWthIGthbm4gRUEoMjEuMyUpIGxlaWNodCBncsO2w59lcmUgVmVya2F1ZnN6YWhsZW4gaW0gdmVyZ2xlaWNoIG1pdCBOaW50ZW5kbyAoMjkuMyUpIGFscyBub2NoIEdsb2JhbCB2ZXJidWNoZW4gZGllc2Ugc2luZCBqZWRvY2ggZ2VyaW5nZXIgYWxzIG5vY2ggaW4gRXVyb3BhLiBJbSBnZWdlbnNhdHogenUgRXVyb3BhIHNjaGVpbnQgamVkb2NoIEFjdGl2aXNpb24gKDE1LjQlKSBpbiBBbWVyaWthIGRldXRsaWNoIGJlbGllYnRlciB6dSBzZWluLiBEaWUgd2VpdGVyZW4gUHVibGlzaGVyIHNpbmQgYXVjaCB3ZWl0ZXJoaW4gbmljaHQgUmVsZXZhbnQuDQoNCiMjIyMgSmFwYW4NCg0KYGBge3IgcGxvdChQdWJsaXNoZXJSYW5raW5nX0pQMiksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShBbnphaGwgPW4oKSxzdW0oSlBfU2FsZXMpKSAlPiUNCiAgZmlsdGVyKEFuemFobD4xMDApICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oSlBfU2FsZXMpIg0KICAgICkNCg0KUHVibGlzaGVyU2FsZXMgPC0gdmdzYWxlcyAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSBmaWx0ZXIoR2xvYmFsX1NhbGVzPjMwMCkNCg0KDQoNCmdyb3VwZWQgPC0gZ3JvdXBlZCAgJT4lIGZpbHRlcihQdWJsaXNoZXIgJWluJSBQdWJsaXNoZXJTYWxlcyRQdWJsaXNoZXIpDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiRW50ZXJ0YWlubWVudCIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiSW50ZXJhY3RpdmUiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIlN0dWRpb3MiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkdhbWVzIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFB1Ymxpc2hlcikNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQdWJsaXNoZXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkpQIHZlcmvDpHVmZSAoaW4gbWlvKSINCg0KKQ0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9waWUodmFsdWVzID1+R2xvYmFsX1NhbGVzLGxhYmVscz1+UHVibGlzaGVyLA0KICAgICAgICAgICBuYW1lPSJKUCBWZXJrYXVmc3phaGxlbiBwcm8gUHVibGlzaGVyIg0KICAgICAgICAgICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJKUCBWZXJrYXVmc3phaGxlbiBwcm8gUHVibGlzaGVyIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCg0KSmFwYW4gWmVpZ3QgaGllciB3b2hsIGRlbiBEZXV0bGljaHN0ZW4gdW50ZXJzY2hpZWQgYXVmLiBOaW50ZW5kbyAoODAuMSUpIERvbWluaWVydCBoaWVyIGRpZSBWZXJrYXVmc3phaGxlbiBtaXQgZGVyIG1laHIgYWxzIDYgZmFjaGVuIG1lbmdlIGFuIHZlcmvDpHVmZW4gYWxzIFNvbnkgKDEzJSkgd2VsY2hlIHNpY2ggZGVuIDIuIFBsYXR6IHNpY2hlcm4uIERpZSBhbmRlcmVuIFB1Ymxpc2hlciBzaW5kIG1pdCB3ZW5pZ2VyIGFscyAyLjUlIGFsbGUgZmFzdCBnbGVpY2ggaXJyZWxldmFudCBpbiBKYXBhbi4gDQoNCiMjIHstfQ0KDQpad2lzY2hlbiBFVSB1bmQgVVMgbGFzc2VuIHNpY2ggaGllciBrYXVtIFVudGVyc2NoaWVkZSBmZXN0c3RlbGxlbiBpbiBKYXBhbiBoaW5nZWdlbiBpc3QgZWluZSBkZXV0bGljaGUgdmVyc2NoaWVidW5nIHp1IGVya2VubmVuLiBKYXBhbmlzY2hlIFB1Ymxpc2hlciBmw7xocmVuIGhpZXJiZWkgZGllIExpc3RlIGFuIHVuZCBkcsOkbmdlbiBhbmRlcmUgZ3Jvw59lIHVudGVybmVobWVuIHZvbiBkZW4gVG9wIHNwb3RzLiBEZW1lbnRzcHJlY2hlbmQga8O2bm5lbiB3aXIgc2NobHVzc2ZvbGdlcm4gZGFzIG1hbmNoZSBSZWdpb25lbiwgdm9yYWxsZW0gSmFwYW4gd2VsY2hlcyBkaWUga2xlaW5zdGUgUmVnaW9uIGlzdCwgZGV1dGxpY2hlIHZvcmxpZWJlbiBpbiBzcGllbGVuIGJlc3RpbW10ZXIgUHVibGlzaGVyIGhhYmVuLCB3ZWxjaGUgdm9uIGRlciBHbG9iYWxlbiBub3JtIEFid2VpY2hlbi4gRWluZSBHZW5hdWVyZSBBbmFseXNlIHZvbiBFdXJvcGEgdW5kIE5vcmQgQW1lcmlrYSBkdXJjaCB1bnRlcnRlaWx1bmcgaW4gTMOkbmRlci9TdGFhdGVuIHfDpGhyZSBoaWVyIHZlcm11dGxpY2ggZGV1dGxpY2ggaW50ZXJlc3NhbnRlciB3aXJkIHZvbiBkZW4gRGF0ZW4gamVkb2NoIGxlaWRlciBuaWNodCBhbmdlYm90ZW4uDQoNCioqKg0KDQojIEdlbnJldmVydGVpbHVuZyBkZXIgVmlkZW9zcGllbGUgbmFjaCBBbnphaGwgeyNHZW5yZUFtb3VudEdsb2JhbH0NCg0KRGEgd2lyIHVucyBudSBrbGFyIGdld29yZGVuIHNpbmQsIGRhc3MgZXMgYmVzdGltbXRlIFB1Ymxpc2hlciBnaWJ0LCBkaWUgYmVsaWVidGVyIHNpbmQgYWxzIGFuZGVyZSB3w6RyZSBlcyBpbnRlcmVzc2FudCBoZXJhdXN6dWZpbmRlbiBvYiBiZXN0aW1tdGUgU3BpZWxlIEdlbnJlcyBiZWxpZWJ0ZXIgc2luZCBhbHMgYW5kZXJlLiBIaWVyenUgdmVyZ2xlaWNoZW4gd2lyIHp1ZXJzdCBlaW5tYWwgZGllIEdlbnJlcyBuYWNoIGFuemFobCBkZXIgU3BpZWxlcmVsZWFzZXMgdW5kIHZlcndlbmRlbiBlcm5ldXQgZWluIFtQYXJldG8tXSgjUGxhdGZvcm1hbmFseXNlKSB1bmQgW0tyZWlzZGlhZ3JhbW1dKCNQbGF0Zm9ybVJhbmtpbmdCeVJlZ2lvbikuIEFuenVtZXJrZW4gaXN0IGhpZXJiZWkgamVkb2NoIGRhcyBTcGllbGUgbWVpc3QgbWVociBhbHMgZWluZW0gR2VucmUgYW5nZWjDtnJlbiBpbiBkaWVzZW0gRGF0ZW5zYXR6IGlzdCBqZWRvY2ggaW1tZXIgbnVyIGVpbnMgYW5nZWdlYmVuLg0KDQojIyBHZW5yZSBuYWNoIEFuemFobCB7LnRhYnNldH0NCg0KIyMjIEJhbGtlbmRpYWdyYW1tDQoNCmBgYHtyIHBsb3QoR2VucmVBbW91bnRfR0xvYmFsMSksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoR2VucmUpICU+JSANCiAgc3VtbWFyaXplKEFuemFobCA9bigpKQ0KDQpncm91cGVkJEFuemFobDwtYXNfdmVjdG9yKGdyb3VwZWQkQW56YWhsKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkQW56YWhsKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRHZW5yZSA8LSBhc19mYWN0b3Iob3JkZXJlZCRHZW5yZSkNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJHZW5yZSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiQW56YWhsIg0KDQopDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoR2VucmUsQW56YWhsLCAuZGVzYz0idHJ1ZSIpLA0KICAgICAgICAgICB5PX5BbnphaGwsDQogICAgICAgICAgIG5hbWU9IlZpZGVvc3BpZWxhbnphaGwgbmFjaCBHZW5yZSINCiAgICAgICAgICAgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlZpZGVvc3BpZWxhbnphaGwgbmFjaCBHZW5yZSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KDQpgYGANCg0KRGVyIEFuZsO8aHJlciBkZXIgTGlzdGUgaXN0IG1pdCBkZXV0bGljaGVtIEFic3RhbmQgQWN0aW9uIChHVEEsQmxvb2Rib3JuZSkgbWl0IDMzMTYuIEF1ZiBkZW0gWndlaXRlbiBwbGF0eiBmaW5kZXQgc2ljaCBTcG9ydHMgKDIzNDYpIG1pdCByZWloZW4gd2llIEZJRkEgdW5kIE5CQTJrLiBEZW4gZHJpdHRlbiBQbGF0eiBiZWxlZ3QgZWluIEdlbnJlIGRhcyBhdXMgdmllbGVuIHZlcnNjaGllZGVuZW4gR2VucmVuIGJlc3RlaHQgZGllIGluIGRpZXNlciBMaXN0ZSBuaWNodCBhdWZnZWbDvGhydCB3ZXJkZW4gbWl0IDE3MzkuIE1pc2MgYmVpbmhhbHRldCBzcGllbGUgd2llIEp1c3QgRGFuY2UgKE11c2lrL1JoeXRobXVzKSBvZGVyIE1pbmVjcmFmdCBlaW4gU2FuZGJveCBTdXJ2aXZhbCBnYW1lLiBEYW5hY2gga29tbWVuIG1pdCBnZXJpbmdlcmVtIEFic3RhbmQgZGVyIFJlaWhlIG5hY2ggUm9sZS1QbGF5aW5nIChXaXRjaGVyLCBUaGUgRWxkZXIgU2Nyb2xscykgbWl0IDE0ODgsIFNob290ZXIgKENhbGwgb2YgRHV0eSwgRG9vbSkgbWl0IDEzMTAsIEFkdmVudHVyZSAoR29kIG9mIFdhciwgTGlmZSBpcyBTdHJhbmdlKSBtaXQgMTI4NiB1bmQgUmFjaW5nIChHcmFuIFRvdXJpc21vLCBGb3J6YSkgbWl0IDEyNDkuIERhbmFjaCBmb2xnZW4gbWl0IGVpbmVtIGdyw7bDn2VyZW4gQWJzdGFuZCBQbGF0Zm9ybSAoU3VwZXIgTWFyaW8sIExpdHRsZUJpZ1BsYW5ldCkgbWl0IDg4NiwgU2ltdWxhdGlvbiAoU2ltcywgTWljcm9zb2Z0IEZsaWdodCBTaW11bGF0b3IpIG1pdCA4Njcgc293aWUgRmlnaHRpbmcgKFRla2tlbiwgU3VwZXIgU21hc2ggQnJvcykgbWl0IDg4NC4gWnUgZ3V0ZXIgbGV0enQgZmVobGVuIG5vY2ggU3RyYXRlZ3kgKEFnZSBvZiBFbXBpcmVzLCBDaXZpbGlzYXRpb24pIG1pdCA2ODEgc293aWUgUHV6emxlIChQb3J0YWwsVGV0cmlzKSBtaXQgNTgyLg0KDQojIyMgS3JlaXNkaWFncmFtbQ0KDQpgYGB7ciBwbG90KEdlbnJlQW1vdW50X0dMb2JhbDIpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShBbnphaGwgPW4oKSkNCg0KZ3JvdXBlZCRBbnphaGw8LWFzX3ZlY3Rvcihncm91cGVkJEFuemFobCkNCm9yZGVyZWQgPC0gZ3JvdXBlZFtvcmRlcihncm91cGVkJEFuemFobCksIGRlY3JlYXNpbmcgPSBGQUxTRV0NCm9yZGVyZWQkR2VucmUgPC0gYXNfZmFjdG9yKG9yZGVyZWQkR2VucmUpDQoNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkFuemFobCINCg0KKQ0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9waWUodmFsdWVzID1+QW56YWhsLGxhYmVscz1+R2VucmUsDQogICAgICAgICAgIG5hbWU9IlZpZGVvc3BpZWxhbnphaGwgbmFjaCBHZW5yZSINCiAgICAgICAgICAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iVmlkZW9zcGllbGFuemFobCBuYWNoIEdlbnJlIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCg0KRGVyIEFuZsO8aHJlciBkZXIgTGlzdGUgaXN0IG1pdCBkZXV0bGljaGVtIEFic3RhbmQgQWN0aW9uIChHVEEsQmxvb2Rib3JuZSkgbWl0IDIwJS4gQXVmIGRlbSBad2VpdGVuIHBsYXR6IGZpbmRldCBzaWNoIFNwb3J0cyAoMTQuMSUpIG1pdCByZWloZW4gd2llIEZJRkEgdW5kIE5CQTJrLiBEZW4gZHJpdHRlbiBQbGF0eiBiZWxlZ3QgZWluIEdlbnJlIGRhcyBhdXMgdmllbGVuIHZlcnNjaGllZGVuZW4gR2VucmVuIGJlc3RlaHQgZGllIGluIGRpZXNlciBMaXN0ZSBuaWNodCBhdWZnZWbDvGhydCB3ZXJkZW4gbWl0IDEwLjUlLiBNaXNjIGJlaW5oYWx0ZXQgc3BpZWxlIHdpZSBKdXN0IERhbmNlIChNdXNpay9SaHl0aG11cykgb2RlciBNaW5lY3JhZnQgZWluIFNhbmRib3ggU3Vydml2YWwgZ2FtZS4gRGFuYWNoIGtvbW1lbiBtaXQgZ2VyaW5nZXJlbSBBYnN0YW5kIGRlciBSZWloZSBuYWNoIFJvbGUtUGxheWluZyAoV2l0Y2hlciwgVGhlIEVsZGVyIFNjcm9sbHMpIG1pdCA4Ljk2JSwgU2hvb3RlciAoQ2FsbCBvZiBEdXR5LCBEb29tKSBtaXQgNy44OSUsIEFkdmVudHVyZSAoR29kIG9mIFdhciwgTGlmZSBpcyBTdHJhbmdlKSBtaXQgNy43NSUgdW5kIFJhY2luZyAoR3JhbiBUb3VyaXNtbywgRm9yemEpIG1pdCA3LjUzJS4gRGFuYWNoIGZvbGdlbiBtaXQgZWluZW0gZ3LDtsOfZXJlbiBBYnN0YW5kIFBsYXRmb3JtIChTdXBlciBNYXJpbywgTGl0dGxlQmlnUGxhbmV0KSBtaXQgNS4zNCUsIFNpbXVsYXRpb24gKFNpbXMsIE1pY3Jvc29mdCBGbGlnaHQgU2ltdWxhdG9yKSBtaXQgNS4yMiUgc293aWUgRmlnaHRpbmcgKFRla2tlbiwgU3VwZXIgU21hc2ggQnJvcykgbWl0IDUuMTElLiBadSBndXRlciBsZXR6dCBmZWhsZW4gbm9jaCBTdHJhdGVneSAoQWdlIG9mIEVtcGlyZXMsIENpdmlsaXNhdGlvbikgbWl0IDQuMSUgc293aWUgUHV6emxlIChQb3J0YWwsVGV0cmlzKSBtaXQgMy41MSUuDQoNCiMjIHstfQ0KDQpBdWZmw6RsbGlnIGhpZXJiZWkgaXN0IGRhcyBkaWUgR3LDtsOfdGVuIHZpZXIgR2VucmVzIDUzLjU2JSBkZXIgU3BpZWxlcmVsZWFzZXMgYXVzbWFjaGVuLiBEaWVzIGlzdCBhbnNpY2ggbmljaHQgd2VpdGVyIFZlcnd1bmRlcmxpY2guIEluIGRlciBTcGllbGVpbmR1c3RyaWUgYnp3IGFsbGdlbWVpbiwgaXN0IGVzIGVpbiBnZXJuZSBnZW51dHp0ZXMga29uemVwdCBGdW5rdGlvbmllcmVuZGUgZGluZ2UgenUgw7xiZXJuZWhtZW4uIERpZXMgaXN0IHZvcmFsbGVtIGF1ZmbDpGxsaWcgYmVpIFNwaWVsZW4sIHdlbGNoZSBnYW56ZSBHZW5yZXMgcHLDpGdlbi4gU2VpIGVzIE1pbmVjcmFmdCBmw7xyIGRpZSBTdXJ2aXZhbCBHYW1lcyAoRGF5WiwgUnVzdCksIFdvcmxkIG9mIFdhcmNyYWZ0IGbDvHIgZGllIE1NT1JQRydzIChGaW5hbCBGYW50YXN5IDE0LCBHdWlsZCBXYXJzIDIpIG9kZXIgZGllIFdhcmNyYWZ0IDMgbW9kIERvdGEgd2VsY2hlIGRhcyBNT0JBIGdlbnJlIChMZWFndWUgb2YgTGVnZW5kcywgRG90YSAyKSBuYWNoIHNpY2ggZ2V6b2dlbiBoYXQuDQoNCioqKg0KDQojIEdlbnJldmVydGVpbHVuZyBkZXIgVmlkZW9zcGllbGUgbmFjaCBWZXJrYXVmc3phaGxlbiB7I0dlbnJlU2FsZXNHbG9iYWx9DQoNClNjaGF1ZW4gd2lyIHVucyBudW4gamVkb2NoIGFuIG9iIGRpZSBWZXJrYXVmc3phaGxlbiBkaWUgZ2xlaWNoZW4gaMOkdWZ1bmdlbiBhdWZ6ZWlnZW4gdW5kIHZlcndlbmRlbiB3aWVkZXIgZWluIFtQYXJldG8tXSgjUGxhdGZvcm1hbmFseXNlKSB1bmQgW0tyZWlzZGlhZ3JhbW1dKCNQbGF0Zm9ybVJhbmtpbmdCeVJlZ2lvbikuIEVzIGdpbHQgd2VpdGVyaGluIGRpZSBvYmVuZ2VuYW5udGUgUHJvYmxlbWF0aWsgZGVyIEdlbnJlbm90YXRpb24gZGVzIERhdGVuc2F0emVzLg0KDQojIyBWZXJrYXVmc3phaGxlbiB7LnRhYnNldH0NCg0KIyMjIEJhbGtlbmRpYWdyYW1tDQoNCmBgYHtyIHBsb3QoU2FsZXNCeUdlbnJlX0dsb2JhbDEpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoR2VucmUpICU+JSANCiAgc3VtbWFyaXplKHN1bShHbG9iYWxfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJWZXJrw6R1ZmUgKGluIG1pbykiDQoNCikNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfYmFycyh4PX5mY3RfcmVvcmRlcihHZW5yZSxHbG9iYWxfU2FsZXMsIC5kZXNjPSJ0cnVlIiksDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgbmFtZT0iVmVya2F1ZnN6YWhsZW4gbmFjaCBHZW5yZSINCiAgICAgICAgICAgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlZlcmthdWZzemFobGVuIG5hY2ggR2VucmUiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCg0KYGBgDQoNCkF1ZiBQbGF0eiAxIHVuZCAyIGRlciBMaXN0ZSBiZWZpbmRlbiBzaWNoIHdlaXRlcmhpbiBBY3Rpb24gKDEuNzUxIG1yZCkgdW5kIFNwb3RzICgxLjMzIG1yZCkuIFBsYXR6IDMgYmVsZWd0IGhpZXIgamVkb2NoIG5pY2h0IE1pc2Mgd2VsY2hlcyBtaXQgODA5Ljk2IG1pbyBhdWYgcGxhdHogNiBhYmdlcnV0c2NodCBpc3Qgc29uZGVybiBTaG9vdGVyICgxLjAzNyBtcmQpLiBQbGF0eiA0IHdpcmQgd2VpdGVyaGluIHZvbiBSb2xlLVBsYXlpbmcgKDkyNy4zNyBtaW8pIGJlbGVndC4gQXVjaCBQbGF0Zm9ybSAoODMxLjM3KSB2ZXJrYXVmZW4gc2ljaCBkZXV0bGljaCBiZXNzZXIgdW5kIHNpY2hlcm4gc2ljaCBQbGF0eiA1LiBEaWUgcmVzdGxpY2hlbiBHZW5yZXMgdW50ZXJzY2hlaWRlbiBzaWNoIEthdW0gaW4gQW56YWhsIHVuZCBWZXJrYXVmc3phaGxlbi4NCg0KDQojIyMgS3JlaXNkaWFncmFtbQ0KDQpgYGB7ciBwbG90KFNhbGVzQnlHZW5yZV9HbG9iYWwyKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJHZW5yZSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiVmVya8OkdWZlIChpbiBtaW8pIg0KDQopDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX3BpZSh2YWx1ZXMgPX5HbG9iYWxfU2FsZXMsbGFiZWxzPX5HZW5yZSwNCiAgICAgICAgICAgbmFtZT0iVmVya2F1ZnN6YWhsZW4gbmFjaCBHZW5yZSINCiAgICAgICAgICAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iVmVya2F1ZnN6YWhsZW4gbmFjaCBHZW5yZSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICApDQpgYGANCg0KQXVmIFBsYXR6IDEgdW5kIDIgZGVyIExpc3RlIGJlZmluZGVuIHNpY2ggd2VpdGVyaGluIEFjdGlvbiAoMTkuNiUpIHVuZCBTcG90cyAoMTQuOSUpLiBQbGF0eiAzIGJlbGVndCBoaWVyIGplZG9jaCBuaWNodCBNaXNjIHdlbGNoZXMgbWl0IDkuMDglIGF1ZiBwbGF0eiA2IGFiZ2VydXRzY2h0IGlzdCBzb25kZXJuIFNob290ZXIgKDExLjYlKS4gUGxhdHogNCB3aXJkIHdlaXRlcmhpbiB2b24gUm9sZS1QbGF5aW5nICgxMC40JSkgYmVsZWd0LiBBdWNoIFBsYXRmb3JtICg5LjMyJSkgdmVya2F1ZmVuIHNpY2ggZGV1dGxpY2ggYmVzc2VyIHVuZCBzaWNoZXJuIHNpY2ggUGxhdHogNS4gRGllIHJlc3RsaWNoZW4gR2VucmVzIHVudGVyc2NoZWlkZW4gc2ljaCBLYXVtIGluIEFuemFobCB1bmQgVmVya2F1ZnN6YWhsZW4uDQoNCiMjIHstfQ0KDQpCZWltIEJldHJhY2h0ZW4gZsOkbGx0IGhpZXIgYXVmLCBkYXNzIHNpY2ggZWluaWdlIEdlbnJlcyBkZXV0bGljaCBiZXNzZXIgdmVya2F1ZmVuIGFscyBhbmRlcmUuIFZvcmFsbGVtIFNob290ZXIgdW5kIFBsYXRmb3JtIHNwaWVsZSBzaW5kIGhpZXIgZGllIEthc3NlbnNjaGxhZ2VyIHdlbm4gbWFuIGRpZSBWZXJrYXVmc3phaGxlbiBtaXQgQW56YWhsIGRlciBTcGllbGUgdmVyZ2xlaWNodC4gRGllIGdyb8OfZW4gR2VucmVzIEFjdGlvbiB1bmQgU3BvcnRzIHNpbmQgamVkb2NoIHNvd29obCBpbiB2ZXJrYXVmc3phaGxlbiBhbHMgYXVjaCBBbnphaGwgZGVyIFNwaWVsZSB1bmFuZ2Vmb2NodGVuIGF1ZiBwbGF0eiAxIHVuZCAyLg0KDQoqKioNCg0KIyBSZWdpb25hbGUgVW50ZXJzY2hpZWRlIGRlciBHZW5yZXMgeyNHZW5yZUFtb3VudEJ5UmVnaW9ufQ0KDQpOYWNoZGVtIHdpciB2b3JoaW4gYmVpIGRlbiBbUGxhdGZvcm1lbl0oI1BsYXRmb3JtUmFua2luZ0J5UmVnaW9uKSBkZXV0bGljaGUgUmVnaW9uYWxlIFVudGVyc2NoaWVkZSBmZXN0c3RlbGxlbiBrb25udGVuIHN0ZWxsdCBzaWNoIGJlaSBkZW4gR2VucmVzIGRpZSBnbGVpY2hlIEZyYWdlIHVuZCBkZW1lbnRzcHJlY2hlbmQgYXVjaCB3aWVkZXIgZGVyIGdsZWljaGUgTMO2c3VuZ3NhbnNhdHogbWl0IFtQYXJldG8tXSgjUGxhdGZvcm1hbmFseXNlKSB1bmQgW0tyZWlzZGlhZ3JhbW1lbl0oI1BsYXRmb3JtUmFua2luZ0J5UmVnaW9uKS4NCg0KIyMgVmVya8OkdWZlIHBybyBHZW5yZSB7LnRhYnNldH0NCg0KIyMjIEJhbGtlbmRpYWdyYW1tZSB7LnRhYnNldH0NCg0KIyMjIyBFdXJvcGENCg0KYGBge3IgcGxvdChTYWxlc0J5R2VucmVfRVUxKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oRVVfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShFVV9TYWxlcykiDQogICAgKQ0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCm9yZGVyZWQgPC0gZ3JvdXBlZFtvcmRlcihncm91cGVkJEdsb2JhbF9TYWxlcyksIGRlY3JlYXNpbmcgPSBGQUxTRV0NCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlZlcmvDpHVmZSAoaW4gbWlvKSINCg0KKQ0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9iYXJzKHg9fmZjdF9yZW9yZGVyKEdlbnJlLEdsb2JhbF9TYWxlcywgLmRlc2M9InRydWUiKSwNCiAgICAgICAgICAgeT1+R2xvYmFsX1NhbGVzLA0KICAgICAgICAgICBuYW1lPSJWZXJrYXVmc3phaGxlbiBuYWNoIEdlbnJlIChFVSkiDQogICAgICAgICAgICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJWZXJrYXVmc3phaGxlbiBuYWNoIEdlbnJlIChFVSkiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KRXVyb3BhIHNpZWh0IHdpZSBiZXJlaXRzIGluIGRlciBbUGxhdGZvcm1hbmFseXNlXSgjUGxhdGZvcm1SYW5raW5nQnlSZWdpb24pIGZlc3RnZXN0ZWxsdCBkZW0gR2xvYmFsZW4gR2VucmV2ZXJnbGVpY2ggcmVjaHQgw6RobmxpY2guIEFjdGlvbiAoNTI1IG1pbykgZsO8aHJ0IHdlaXRlcmhpbiB2b3IgU3BvcnRzKDM3Ni44NSBtaW8pIHVuZCBTaG9vdGVybiAoMzEzLjI3IG1pbykuIEF1ZiBwbGF0eiA0IGlzdCBkYW5uIGRlciBlcnN0ZSBVbnRlcnNjaGllZCBmZXN0c3RlbGxiYXIuIEFuc3RhdHQgUm9sZS1QbGF5aW5nICgxODguMDYgbWlvKSB3ZWxjaGVzIGF1ZiBQbGF0eiA3IGFiZ2VydXRzY2h0IGlzdCBiZWZpbmRldCBzaWNoIGhpZXIgUmFjaW5nICgyMzguMzkpIHdlbGNoZSBkZW4gUGxhdHogdGF1c2NoZW4uIEF1Y2ggUGxhdHogNSBNaXNjICgyMTUuOTggbWlvKSB1bmQgUGxhdHogNiBQbGF0Zm9ybSAoMjAxLjYzIG1pbykgc2luZCBpbiBFdXJvcGEgdmVydGF1c2NodC4gQWxsZ2VtZWluIHNjaGVpbnQgaGllciBhdWYgZGVuIGhpbnRlcmVuIEdlbnJlcGzDpHR6ZW4gZWluZSB2ZXJzY2hpZWJ1bmcgZmVzdHN0ZWxsYmFyIHp1IHNlaW4gZGVubiBvYndvaGwgZGFzIHZlcmjDpGx0bmlzIGRlciBHZW5yZXMgZ2xlaWNoIGJsZWlidCBzaW5kIHp1c8OkdHpsaWNoIHNvd29obCBTaW11bGF0aW9uICgxMTMuMzggbWlvKSB1bmQgRmlnaHRpbmcgKDEwMS4zMiBtaW8pIGFscyBhdWNoIEFkdmVudHVyZSAoNjMuMTMgbWlvKSB1bmQgUHV6emxlICg1MC43OCBtaW8pIHZlcnRhdXNjaHQuIFZvbiBkZW4gaGludGVyZW4gUGzDpHR6ZW4gYmxlaWJ0IHNvbWl0IGVpbnppZyBTdHJhdGVneSAoNDUuMzQgbWlvKSBhdWYgc2VpbmVtIHZvcmhlcmlnZW4gbGV0enRlbiBwbGF0ei4NCg0KIyMjIyBOb3JkLUFtZXJpa2ENCmBgYHtyIHBsb3QoU2FsZXNCeUdlbnJlX05BMSksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShHZW5yZSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKE5BX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oTkFfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJWZXJrw6R1ZmUgKGluIG1pbykiDQoNCikNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfYmFycyh4PX5mY3RfcmVvcmRlcihHZW5yZSxHbG9iYWxfU2FsZXMsIC5kZXNjPSJ0cnVlIiksDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgbmFtZT0iVmVya2F1ZnN6YWhsZW4gbmFjaCBHZW5yZSAoTkEpIg0KICAgICAgICAgICAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iVmVya2F1ZnN6YWhsZW4gbmFjaCBHZW5yZSAoTkEpIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCkF1Y2ggaW4gTm9yZC1BbWVyaWthIGlzdCBlaW5lIFZlcnNjaGllYnVuZyBkZXIgR2VucmVzIGZlc3R6dXN0ZWxsZW4uIERpZSBUb3AgMyBzaW5kIHdlaXRlcmhpbiB2b24gQWN0aW9uICg4NzcuODMgbWlvKSwgU3BvcnRzICg2ODMuMzUgbWlvKSB1bmQgU2hvb3RlciAoNTgyLjYgbWlvKSBiZWxlZ3QuIEltIGdlZ2Vuc2F0eiB6dSBFdXJvcGEgc2luZCBoaWVyIGFsbGVyZGluZ3MgbnVyIFBsYXR6IDQgUGxhdGZvcm0gKDQ0Ny4wNSBtaW8pLCBQbGF0eiA1IE1pc2MgKDQxMC4yNCBtaW8pIHNvd2llIFBsYXR6IDYgUmFjaW5nICgzNTkuNDIpIHVuZCBQbGF0eiA3IFJvbGUtUGxheWluZyAoMzI3LjI4IG1pbykgdmVydGF1c2NodC4gUGxhdHogOCBiaXMgMTIgc2luZCB3aWUgZGllIGdsb2JhbGVuIFJlZmVyZW56d2VydGUgYW5nZW9yZG5ldCBkZXIgZWluemlnZSBVbnRlcnNjaGllZCB6d2lzY2hlIEdsb2JhbCB1bmQgTm9yZC1BbWVyaWthIGlzdCBzb21pdCBkaWUgdmVyc2NoaWVidW5nIHZvbiBSb2xlLVBsYXlpbmcgYXVmIFBsYXR6IDcuDQoNCiMjIyMgSmFwYW4NCg0KYGBge3IgcGxvdChTYWxlc0J5R2VucmVfSlAxKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oSlBfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShKUF9TYWxlcykiDQogICAgKQ0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCm9yZGVyZWQgPC0gZ3JvdXBlZFtvcmRlcihncm91cGVkJEdsb2JhbF9TYWxlcyksIGRlY3JlYXNpbmcgPSBGQUxTRV0NCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlZlcmvDpHVmZSAoaW4gbWlvKSINCg0KKQ0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9iYXJzKHg9fmZjdF9yZW9yZGVyKEdlbnJlLEdsb2JhbF9TYWxlcywgLmRlc2M9InRydWUiKSwNCiAgICAgICAgICAgeT1+R2xvYmFsX1NhbGVzLA0KICAgICAgICAgICBuYW1lPSJWZXJrYXVmc3phaGxlbiBuYWNoIEdlbnJlIChKUCkiICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJWZXJrYXVmc3phaGxlbiBuYWNoIEdlbnJlIChKUCkiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCg0KYGBgDQpJbiBKYXBhbiBiZWZpbmRldCBzaWNoIFJvbGUtUGxheWluZyAoMzUyLjMxIG1pbykgbWl0IGdyb8OfZW0gQWJzdGFuZCBhdWYgUGxhdHogMSBub2NoIHZvciBkZSBzb25zdGlnZW4gUGxhdHpoaXJzY2hlbiBBY3Rpb24gKDE1OS45NSBtaW8pIHVuZCBTcG9ydHMgKDEzNS4zNyBtaW8pLiBEaWUgZWhlbWFsaWdlIHRvcCAzIFNob290ZXIgKDM4LjI4IG1pbykgZsOkbGx0IGluIEphcGFuIGF1ZiBkZW4gbGV0enRlbiBwbGF0eiBhYiB1bmQgd2lyZCB2b24gUGxhdGZvcm0gKDEzMC43NyBtaW8pIGVyc2V0enQuIE1pc2MgKDEwNy43NiBtaW8pIGthbm4gc2ljaCB3ZWl0ZXJoaW4gaW0gbWl0dGVsZmVsZCBoYWx0ZW4gd29oaW5nZWdlbiBGaWdodGluZyAoODcuMzUgbWlvKSB1bmQgU2ltdWxhdGlvbiAoNjMuNyBtaW8pIGVpbmlnZSBQbMOkdHplIGd1dCBtYWNoZW4ga8O2bm5lbiB1bmQgbnVuIGF1ZiBQbGF0eiA2IHVuZCA3IHZvcnLDvGNrZW4uIEF1Y2ggUHV6emxlIEdhbWVzICg1Ny4zMSBtaW8pIGVyZnJldWVuIHNpY2ggZWluZXIgaMO2aGVyZW4gYmVsaWVidGhlaXQgYWxzIG5vY2ggR2xvYmFsIHdvaGluZ2VnZW4gUmFjaW5nICg1Ni42OSBtaW8pIGVpbmVuIGRldXRsaWNoZW4gVmVybHVzdCBoaW5uZWhtZW4gbXVzcy4gQWR2ZW50dXJlICg1Mi4wNyBtaW8pIHVuZCBTdHJhdGVneSAoNDkuNDYgbWlvKSBibGVpYmVuIGplZG9jaCB3ZWl0ZXJoaW4gZWluZSBkZXIgVW5iZWxpZWJ0ZXN0ZW4gR2VucmVzLg0KDQojIyMgS3JlaXNkaWFncmFtbWUgey50YWJzZXR9DQoNCiMjIyMgRXVyb3BhDQpgYGB7ciBwbG90KFNhbGVzQnlHZW5yZV9FVTIpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoR2VucmUpICU+JSANCiAgc3VtbWFyaXplKHN1bShFVV9TYWxlcykpICAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEVVX1NhbGVzKSINCiAgICApDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJHZW5yZSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiVmVya8OkdWZlIChpbiBtaW8pIg0KDQopDQoNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfcGllKHZhbHVlcyA9fkdsb2JhbF9TYWxlcyxsYWJlbHM9fkdlbnJlLA0KICAgICAgICAgICBuYW1lPSJWZXJrYXVmc3phaGxlbiBuYWNoIEdlbnJlIChFVSkiICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJWZXJrYXVmc3phaGxlbiBuYWNoIEdlbnJlIChFVSkiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgKQ0KYGBgDQoNCkV1cm9wYSBzaWVodCB3aWUgYmVyZWl0cyBpbiBkZXIgW1BsYXRmb3JtYW5hbHlzZV0oI1BsYXRmb3JtUmFua2luZ0J5UmVnaW9uKSBmZXN0Z2VzdGVsbHQgZGVtIEdsb2JhbGVuIEdlbnJldmVyZ2xlaWNoIHJlY2h0IMOkaG5saWNoLiBBY3Rpb24gKDIxLjYlKSBmw7xocnQgd2VpdGVyaGluIHZvciBTcG9ydHMoMTUuNSUpIHVuZCBTaG9vdGVybiAoMTIuOSUpLiBBdWYgcGxhdHogNCBpc3QgZGFubiBkZXIgZXJzdGUgVW50ZXJzY2hpZWQgZmVzdHN0ZWxsYmFyLiBBbnN0YXR0IFJvbGUtUGxheWluZyAoNy43MyUpIHdlbGNoZXMgYXVmIFBsYXR6IDcgYWJnZXJ1dHNjaHQgaXN0IGJlZmluZGV0IHNpY2ggaGllciBSYWNpbmcgKDkuNzklKSB3ZWxjaGUgZGVuIFBsYXR6IHRhdXNjaGVuLiBBdWNoIFBsYXR6IDUgTWlzYyAoOC44NyUpIHVuZCBQbGF0eiA2IFBsYXRmb3JtICg4LjI4JSkgc2luZCBpbiBFdXJvcGEgdmVydGF1c2NodC4gQWxsZ2VtZWluIHNjaGVpbnQgaGllciBhdWYgZGVuIGhpbnRlcmVuIEdlbnJlcGzDpHR6ZW4gZWluZSB2ZXJzY2hpZWJ1bmcgZmVzdHN0ZWxsYmFyIHp1IHNlaW4gZGVubiBvYndvaGwgZGFzIHZlcmjDpGx0bmlzIGRlciBHZW5yZXMgZ2xlaWNoIGJsZWlidCBzaW5kIHp1c8OkdHpsaWNoIHNvd29obCBTaW11bGF0aW9uICg0LjY2JSkgdW5kIEZpZ2h0aW5nICg0LjE2JSkgYWxzIGF1Y2ggQWR2ZW50dXJlICgyLjYzJSkgdW5kIFB1enpsZSAoMi4wOSUpIHZlcnRhdXNjaHQuIFZvbiBkZW4gaGludGVyZW4gUGzDpHR6ZW4gYmxlaWJ0IHNvbWl0IGVpbnppZyBTdHJhdGVneSAoMS44NiUpIGF1ZiBzZWluZW0gdm9yaGVyaWdlbiBsZXR6dGVuIHBsYXR6Lg0KDQoNCiMjIyMgTm9yZC1BbWVyaWthDQoNCmBgYHtyIHBsb3QoU2FsZXNCeUdlbnJlX05BMiksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShHZW5yZSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKE5BX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oTkFfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJWZXJrw6R1ZmUgKGluIG1pbykiDQoNCikNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfcGllKHZhbHVlcyA9fkdsb2JhbF9TYWxlcyxsYWJlbHM9fkdlbnJlLA0KICAgICAgICAgICBuYW1lPSJWZXJrYXVmc3phaGxlbiBuYWNoIEdlbnJlIChOQSkiLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlZlcmthdWZzemFobGVuIG5hY2ggR2VucmUgKE5BKSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICApDQpgYGANCg0KQXVjaCBpbiBOb3JkLUFtZXJpa2EgaXN0IGVpbmUgVmVyc2NoaWVidW5nIGRlciBHZW5yZXMgZmVzdHp1c3RlbGxlbi4gRGllIFRvcCAzIHNpbmQgd2VpdGVyaGluIHZvbiBBY3Rpb24gKDIwJSksIFNwb3J0cyAoMTUuNiUpIHVuZCBTaG9vdGVyICgxMy4zJSkgYmVsZWd0LiBJbSBnZWdlbnNhdHogenUgRXVyb3BhIHNpbmQgaGllciBhbGxlcmRpbmdzIG51ciBQbGF0eiA0IFBsYXRmb3JtICgxMC4yJSksIFBsYXR6IDUgTWlzYyAoOS4zNCUpIHNvd2llIFBsYXR6IDYgUmFjaW5nICg4LjE4JSkgdW5kIFBsYXR6IDcgUm9sZS1QbGF5aW5nICg3LjQ1JSkgdmVydGF1c2NodC4gUGxhdHogOCBiaXMgMTIgc2luZCB3aWUgZGllIGdsb2JhbGVuIFJlZmVyZW56d2VydGUgYW5nZW9yZG5ldCBkZXIgZWluemlnZSBVbnRlcnNjaGllZCB6d2lzY2hlIEdsb2JhbCB1bmQgTm9yZC1BbWVyaWthIGlzdCBzb21pdCBkaWUgdmVyc2NoaWVidW5nIHZvbiBSb2xlLVBsYXlpbmcgYXVmIFBsYXR6IDcuDQoNCiMjIyMgSmFwYW4NCg0KYGBge3IgcGxvdChTYWxlc0J5R2VucmVfSlAyKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oSlBfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShKUF9TYWxlcykiDQogICAgKQ0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCm9yZGVyZWQgPC0gZ3JvdXBlZFtvcmRlcihncm91cGVkJEdsb2JhbF9TYWxlcyksIGRlY3JlYXNpbmcgPSBGQUxTRV0NCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlZlcmvDpHVmZSAoaW4gbWlvKSINCg0KKQ0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9waWUodmFsdWVzID1+R2xvYmFsX1NhbGVzLGxhYmVscz1+R2VucmUsDQogICAgICAgICAgIG5hbWU9IlZlcmthdWZzemFobGVuIG5hY2ggR2VucmUgKEpQKSIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlZlcmthdWZzemFobGVuIG5hY2ggR2VucmUgKEpQKSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICApDQpgYGANCg0KSW4gSmFwYW4gYmVmaW5kZXQgc2ljaCBSb2xlLVBsYXlpbmcgKDI3LjMlKSBtaXQgZ3Jvw59lbSBBYnN0YW5kIGF1ZiBQbGF0eiAxIG5vY2ggdm9yIGRlIHNvbnN0aWdlbiBQbGF0emhpcnNjaGVuIEFjdGlvbiAoMTIuNCUpIHVuZCBTcG9ydHMgKDEwLjUlKS4gRGllIGVoZW1hbGlnZSB0b3AgMyBTaG9vdGVyICgyLjk3JSkgZsOkbGx0IGluIEphcGFuIGF1ZiBkZW4gbGV0enRlbiBwbGF0eiBhYiB1bmQgd2lyZCB2b24gUGxhdGZvcm0gKDEwLjElKSBlcnNldHp0LiBNaXNjICg4LjM1JSkga2FubiBzaWNoIHdlaXRlcmhpbiBpbSBtaXR0ZWxmZWxkIGhhbHRlbiB3b2hpbmdlZ2VuIEZpZ2h0aW5nICg2Ljc3JSkgdW5kIFNpbXVsYXRpb24gKDQuOTMlKSBlaW5pZ2UgUGzDpHR6ZSBndXQgbWFjaGVuIGvDtm5uZW4gdW5kIG51biBhdWYgUGxhdHogNiB1bmQgNyB2b3Jyw7xja2VuLiBBdWNoIFB1enpsZSBHYW1lcyAoNC40NCUpIGVyZnJldWVuIHNpY2ggZWluZXIgaMO2aGVyZW4gYmVsaWVidGhlaXQgYWxzIG5vY2ggR2xvYmFsIHdvaGluZ2VnZW4gUmFjaW5nICg0LjM5JSkgZWluZW4gZGV1dGxpY2hlbiBWZXJsdXN0IGhpbm5laG1lbiBtdXNzLiBBZHZlbnR1cmUgKDQuMDMlKSB1bmQgU3RyYXRlZ3kgKDMuODMlKSBibGVpYmVuIGplZG9jaCB3ZWl0ZXJoaW4gZWluZSBkZXIgVW5iZWxpZWJ0ZXN0ZW4gR2VucmVzLg0KDQojIyB7LX0NCg0KWnUgZXJrZW5uZW4gaXN0IGhpZXIgZXJuZXV0IGRhcyBBbWVyaWthIHVuZCBFdW9wYSByZWNodCDDpGhubGljaCBpbnRlcmVzc2VuIGhhYmVuIHVuZCBudXIgYXVmIGRlbiBtaXR0bGVyZW4gdW5kIGhpbnRlcmVuIHBsw6R0emVuIHVudGVyc2NoaWVkZSBhdWZ3ZWlzZW4uIE5vcmQtQW1lcmlrYSBpc3QgYWxzIGRlciBncsO2w590ZSBNYXJrdCB3aWUgenUgZXJ3YXJ0ZW5kIGFtIG7DpGNoc3RlbiBhbiBkZW4gR2xvYmFsZW4gUmVmZXJlbnpkYXRlbiB3b2hpbmdlZ2VuIEphcGFuIGVpbiBnw6RuemxpY2ggYW5kZXJlcyBHZW5yZXNoZW1hIGVya2VubmVuIGzDpHNzdC4gSW4gSmFwYW4gZG9taW5pZXJ0IFJvbGUtUGxheWluZyB3ZWxjaGVzIHNpY2ggaW4gRXVyb3BhIHVuZCBBbWVyaWthIG51ciBhdWYgcGxhdHogNyBiZWZpbmRldCB3ZWxjaGVzIGR1cmNoIGRpZSBKYXBhbmlzY2hlIEt1bHR1ciBnZXByw6RndCBhdWNoIHNpbm4gZXJnaWJ0Lg0KDQoqKioNCg0KIyBHZW5yZWVudHdpY2tsdW5nIGltIGxhdWZlIGRlciBKYWhyZSBuYWNoIGFuemFobCB7I0dlbnJlQW1vdW50UGVyWWVhcn0NCg0KTmFjaGRlbSB3aXIgdW5zIG51biDDnGJlciBkaWUgR2VucmV2ZXJ0ZWlsdW5nIEdsb2JhbCB1bmQgaW4gZGVuIGVpbnplbG5lbiBSZWdpb25lbiBlaW4gQmlsZCBnZW1hY2h0IGhhYmVuIHfDpHJlIGVzIGludGVyZXNzYW50IGFuenVzY2hhdWVuIHdpZSBzaWNoIGRpZSBHZW5yZXMgaW0gTGF1ZmUgZGVyIEphaHJlIGVudHdpY2tlbHQgaGFiZW4gdW5kIG9iIHNpY2ggZWluIFRyZW5kIGJlaSBHZXdpc3NlbiBHZW5yZXMgZXJrZW5uZW4gbMOkc3N0LiBBbHMgZXJzdGVzIEJldHJhY2h0ZW4gd2lyIHJlaW5lIEFuemFobCBkZXIgU3BpZWxlcmVsZWFzZXMgdW5kIFtzcMOkdGVyXSgjR2VucmVTYWxlc1BlclllYXIpIGRpZSB2ZXJrYXVmc3phaGxlbi4gSGllcnp1IHZlcndlbmRlbiB3aXIgdmVyc2NoaWVkZW5lIExpbmVwbG90cyBkaWUgc2ljaCBpbiBkZXIgRGF0ZW52b3JiZXJlaXR1bmcgbmljaHQgZ3Jvw59hcnRpZyB2b24gZGVuIFtQYXJldG8tXSgjUGxhdGZvcm1hbmFseXNlKSB1bmQgW0tyZWlzZGlhZ3JhbW1lbl0oI1BsYXRmb3JtUmFua2luZ0J5UmVnaW9uKSB1bnRlcnNjaGVpZGV0LiBEaWUgdW50ZXJzY2hpZWRlIGluIGRlciBEaWFncmFtbSBlcnN0ZWxsdW5nIHdlcmRlIGljaCBqZWRvY2ggaW0gRm9sZ2VuZGVuIGF1ZnplaWdlbi4NCg0KIyMgQW56YWhsIGRlciBTcGllbGUgcHJvIEdlbnJlIHBybyBKYWhyIHsudGFic2V0fQ0KDQojIyMgTGluZXMNCg0KRGllIGVyc3RlbGx1bmcgZGVzIExpbmVzIERpYWdyYW1tZXMgaXN0IHdvaGwgZGllIHNpbXBlbHN0ZS4gV2lyIHZlcndlbmRlbiB1bnNlcmUgdm9yZ2VmaWx0ZXJ0ZXMgZGF0YS5mcmFtZSAqZmlsdGVyZWQqIHVuZCDDvGJlcmdlYmVuIGRpZXMgYW4gZGllICpwbG90X2x5KCkqIGZ1bmt0aW9uLiBEYW5hY2ggbnV0emVuIHdpciAqYWRkX2xpbmVzKiB1bSBlaW4gTGluaWVuZGlhZ3JhbW0genUgZXJzdGVsbGVuIHVuZCBzZXR6ZW4gZGllIFBhcmFtZXRlci4gRGVyIFgtV2VydCBpc3QgZGFzICpZZWFyKiwgZGVyIFktV2VydCBkaWUgKkFuemFobCouIEFscyAqY29sb3IqIHfDpGhsZW4gd2lyIGRhcyBHZW5yZSB1bmQgdW5zZXJlIEZhcmJ0YWJlbGxlIMO8YmVyZ2ViZW4gd2lyIGFuIGRpZSBmdW5rdGlvbiB2aWEgKmNvbG9ycz0qLg0KDQpgYGB7ciBwbG90KEFtb3VudE9mR2FtZXNCeUdlbnJlYnlZZWFyMSksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGdyb3VwX2J5KFllYXIsIEdlbnJlKSAlPiUNCiAgZHBseXI6OnN1bW1hcml6ZShBbnphaGwgPW4oKSkgJT4lIGZpbHRlcihZZWFyIT0nTi9BJyklPiVmaWx0ZXIoWWVhciE9MjAyMCkgJT4lIGZpbHRlcihZZWFyIT0nMjAxNycpICU+JQ0KICBhcy5kYXRhLmZyYW1lKCkNCg0KDQpmaWx0ZXJlZCA8LSBncm91cGVkICU+JSBzZWxlY3QoWWVhcixHZW5yZSxBbnphaGwpDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJKYWhyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJBbnphaGwiDQoNCikNCg0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KCkgJT4lIA0KICBhZGRfbGluZXMoeD1+WWVhciwNCiAgICAgICAgICAgeT1+QW56YWhsLCBjb2xvcj1+R2VucmUsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogbGF5b3V0KHRpdGxlPSJBbnphaGwgZGVyIFNwaWVsZXJlbGVhc2VzIHZvbiAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCg0KYGBgDQpJbSBlcnN0ZW4gbW9tZW50IGlzdCBkaWVzZXMgRGlhZ3JhbW0gcmVjaHQgdW7DvGJlcnNpY2h0bGljaCBkb2NoIGJlaSBnZW5hdWVyZW4gQmV0cmFjaHR1bmcga2FubiBlaW4gYXVmbWVya3NhbWVyIEJldHJhY2h0ZXIgYmVyZWl0cyBlaW5pZ2UgRGluZ2UgZXJrZW5uZW4uIFp1bSBlaW5lbiBzZWhlbiB3aXIgZGFzIHp3aXNjaGVuIDE5OTMgdW5kIDIwMDMgdGF0c8OkY2hsaWNoIFNwb3J0cyBkYXMgbWVpc3QgdmVya2F1ZnRlIEdlbnJlIHdhciBiZXZvciBlcyB2b24gQWN0aW9uIGFiZ2Vsw7ZzdCB3dXJkZS4gTWlzYyBnYW1lcyBlcmZyZXV0ZW4gc2ljaCB6d2lzY2hlbiAyMDA1IHVuZCAyMDExIGdyb8OfZXIgYmVsaWVidGhlaXQgYmV2b3IgZGllc2Ugd2llZGVyIGluIGRlciBWZXJzZW5rdW5nIHZlcnNjaHdhbmRlbi4gQXVjaCBBZHZlbnR1cmUgZ2FtZXMgd2FyZW4gendpc2NoZW4gMjAwNyB1bmQgMjAxMCBhbSBiZWxpZWJ0ZXN0ZW4uDQoNCiMjIyBGaWxsZWQgTGluZXMNCg0KRGllIEVyc3RlbGx1bmcgZGVzIEZpbGxlZCBMaW5lcyBEaWFncmFtbWVzIHVudGVyc2NoZWlkZXMgc2ljaCBldHdhcyB2b24gZGVtIGVpbmZhY2ggTGluZXMtUGxvdC4gQW5zdGF0dCBkZXIgKmFkZF9MaW5lcyogZnVua3Rpb24gw7xiZXJnZWJlbiB3aXIgaGllciBkaXJla3QgZGllIFBhcmFtZXRlciBtaXQgYW4gKnBsb3RfbHkoKSouIFggaXN0IHdlaXRlcmhpbiBkYXMgSmFociwgWSBkaWUgQW56YWhsLCBkaWUgRmFyYnRhYmxldHRlICpjb2xvcnMqIHVuZCAqY29sb3I9R2VucmUqLiBEaWUgVW50ZXJzY2hpZWRlIHNpbmQgaGllciBkZXIgKnR5cGUqIHBhcmFtZXRlciB3ZWxjaGVyIGF1ZiBzY2F0dGVyIGdlc2V0eiB3aXJkLCAqbW9kZSogd2VsY2hlcyBub25lIGlzdCB1bmQgKmZpbGwqIHdlbGNoZXMgZHVyY2ggKnRvemVyb3kqIGRpZSBmw7xsbHVuZyBiaXMgenVyIHkgQWNoc2UgZXJ6ZXVndC4NCg0KYGBge3IgcGxvdChBbW91bnRPZkdhbWVzQnlHZW5yZWJ5WWVhcjIpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyLCBHZW5yZSkgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoQW56YWhsID1uKCkpICU+JSBmaWx0ZXIoWWVhciE9J04vQScpJT4lZmlsdGVyKFllYXIhPTIwMjApICU+JSBmaWx0ZXIoWWVhciE9JzIwMTcnKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsR2VucmUsQW56YWhsKQ0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiSmFociINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiQW56YWhsIg0KDQopDQoNCg0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KHggPSB+WWVhciwgeSA9IH5BbnphaGwsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbm9uZScsIGZpbGwgPSAndG96ZXJveScsY29sb3IgPSB+R2VucmUgLGNvbG9ycyA9IG15UGFsZXR0ZSklPiUgDQogIGxheW91dCh0aXRsZT0iQW56YWhsIGRlciBTcGllbGVyZWxlYXNlcyB2b24gMTk4MC0yMDE2IiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCmBgYA0KDQpFaW5pZ2UgZmVpbmVyZSB1bnRlcnNjaGllZGUgTGFzc2VuIHNpY2ggaGllciBkZXV0bGljaCBiZXNzZXIgZXJrZW5uZW4gYWxzIG5vY2ggaW0gTGluZXMgRGlhZ3JhbW0uIE1hbiBlcmtlbm50IGJlaXNwaWVsc3dlaXNlIGRlbiBncm/Dn2VuIFdhY2hzdHVtIHZvbiBTdHJhdGVneSBnYW1lcyB6d2lzY2hlbiAxOTk2IHVuZCAxOTk4IGJldm9yIGRpZXNlIDIwMDAgc3RhcmsgYWJmbGFjaGVuIHVuZCBuaWNodCBtaXQgZGVtIGFsbGdlbWVpbmVuIFdhY2hzdHVtIGRlciBhbmRlcmVuIEdlbnJlcyBtaXRoYWx0ZW4ga8O2bm5lbi4gQXVjaCBkZXIgZ3Jvw59lIFdhY2hzdHVtIHZvbiBSYWNpbmcgZ2FtZXMgendpc2NoZW4gMjAwIHVuZCAyMDA0IGlzdCBndXQgZXJrZW5uYmFyLg0KDQojIyMgU3RhY2tlZCBMaW5lcyB7LmFjdGl2ZX0NCg0KRGEgc3RhY2tlZCBMaW5lcyBzZWhyIMO8YmVyc2ljaHRsaWNoIHVuZCBndXQgZGFyaW4gc2luZCBzaWNoIGVpbmVuIEdyb2JlcmVuIMO8YmVyYmxpY2sgw7xiZXIgZGllIERhdGVuIHp1IHNjaGFmZmVuIHNpbmQgZGllc2UgaGllciBhbHMgZXJzdGUgQW5zaWNodCB2b3JhdXNnZXfDpGhsdC4gVW0gZGllIGhpbnp1Z2Vow7ZyZW5kZSBUZXh0ZSBodW5kZXJ0cHJvemVudGlnIHZlcnN0ZWhlbiB6dSBrw7ZubmVuIGlzdCBlcyBhYmVyIGhpbGZyZWljaCB6dWVyc3QgZGVuIExpbmVzIHVuZCBGaWxsZWQgTGluZXMgdGFiIHp1IHN0dWRpZXJlbi4NCg0KRGllIEVyc3RlbGx1bmcgZGVzIHN0YWNrZWQgTGluZXMgRGlhZ3JhbW0gaXN0IGRlbiBGaWxsZWQgTGluZXMgc2VociDDpGhubGljaC4gRWluemlnZXIgdW50ZXJzY2hpZWQgaXN0IGRpZSBBYndlc2VuaGVpdCBkZXMgKmZpbGwqIHBhcmFtZXRlcnMgdW5kIHN0YXR0ZGVzc2VuIGRpZSB2ZXJ3ZW5kdW5nIHZvbiAqc3RhY2tncm91cD0nb25lJyogd2VsY2hlcyBkaWUgc3RhY2tlZCBMaW5lcyBlcnpldWd0Lg0KDQpgYGB7ciBwbG90KEFtb3VudE9mR2FtZXNCeUdlbnJlYnlZZWFyMyksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGdyb3VwX2J5KFllYXIsIEdlbnJlKSAlPiUNCiAgZHBseXI6OnN1bW1hcml6ZShBbnphaGwgPW4oKSkgJT4lIGZpbHRlcihZZWFyIT0nTi9BJyklPiVmaWx0ZXIoWWVhciE9MjAyMCkgJT4lIGZpbHRlcihZZWFyIT0nMjAxNycpICU+JQ0KICBhcy5kYXRhLmZyYW1lKCkNCg0KDQpmaWx0ZXJlZCA8LSBncm91cGVkICU+JSBzZWxlY3QoWWVhcixHZW5yZSxBbnphaGwpDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJKYWhyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJBbnphaGwiDQoNCikNCg0KDQpmaWx0ZXJlZCAlPiUNCnBsb3RfbHkoeCA9IH5ZZWFyLCB5ID0gfkFuemFobCwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdub25lJywgc3RhY2tncm91cCA9ICdvbmUnLGNvbG9yID0gfkdlbnJlLCBjb2xvcnMgPSBteVBhbGV0dGUpJT4lIA0KICBsYXlvdXQodGl0bGU9IkFuemFobCBkZXIgU3BpZWxlcmVsZWFzZXMgdm9uIDE5ODAtMjAxNiIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KDQpgYGANCg0KTGVpZGVyIHNpbmQgZGllIEZhcmJlbiBhdWZncnVuZCBlaW5lcyBGZWhsZXJzIGhpZXIgZXR3YXMgZmVobGVyaGFmdCBtZWhyIGRhenUgaW0gW0Zheml0XSgjQXVmZ2V0cmV0ZW5lUHJvYmxlbWUpIEJlaW0gQmV0cmFjaHRlbiBkZXMgU3RhY2tlZCBMaW5lIHBsb3RzIHNpbmQgamVkb2NoIHRyb3R6ZGVtIGVpbmlnZSBEaW5nZSBkaXJla3Qgc2VociBndXQgenUgZXJrZW5uZW4uIE1hbiBzaWVodCB3ZWxjaGUgR2VucmVzIGVpbiBncsO2w59lcmVzIFdhY2hzdHVtIGhpbmxlZ2VuIGFscyBhbmRlcmUuIFNvd29obCBTaG9vdGVyIGFscyBhdWNoIFB1enpsZSB1bmQgUGxhdGZvcm0gR2FtZXMgYmxlaWJlbiBpbiBkZW4gMjAxMGVyIGphaHJlbiByZWxhdGl2IGdsZWljaGJsZWliZW5kLiBBY3Rpb24sIFN0cmF0ZWd6LCBNaXNjIHVuZCBTcG9ydHMgR2FtZXMga8O2bm5lbiBqZWRvY2ggZWluIGRldXRsaWNoZXMgV2FjaHN0dW0gYXVmemVpZ2VuLg0KDQoNCiMjIyBHZW5yZXZlcnNjaGllYnVuZw0KDQpTY2hhdWVuIHdpciB1bnMgbnVuIGRpZSBFcnN0ZWxsdW5nIGRlciB6dW0gdmVyZ2xlaWNoZW4gZGVyIEdlbnJlcyB3b2hsIGludGVyZXNzYW50ZXN0ZW4gR3JhZmlrIGFuLiBEaWUgZXJzdGVsbHVuZyBpc3QgaGllciBxdWFzaSBnbGVpY2ggenUgZGVuIFN0YWNrZWQgTGluZXMuIEVpbnppZ2UgbmV1ZXJ1bmcgaXN0IGRhcyBoaW56dWbDvGdlbiBkZXMgUGFyYW1ldGVycyAqZ3JvdXBub3JtID0gJ3BlcmNlbnQnKiB3ZWxjaGVzIGRpZSBZLUFjaHNlIHZvbiBkZW0gd2VydCBkZXIgQW56YWhsIHp1IFByb3plbnR3ZXJ0ZW4gw6RuZGVydC4gQXVjaCBoaWVyIHNpbmQgamVkb2NoIGRpZSBGYXJiZW4gbGVpZGVyIFtGZWhsZXJoYWZ0XSgjQXVmZ2V0cmV0ZW5lUHJvYmxlbWUpLg0KDQpgYGB7ciBwbG90KEFtb3VudE9mR2FtZXNCeUdlbnJlYnlZZWFyNCksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGdyb3VwX2J5KFllYXIsIEdlbnJlKSAlPiUNCiAgZHBseXI6OnN1bW1hcml6ZShBbnphaGwgPW4oKSkgJT4lIGZpbHRlcihZZWFyIT0nTi9BJyklPiVmaWx0ZXIoWWVhciE9MjAyMCkgJT4lIGZpbHRlcihZZWFyIT0nMjAxNycpICU+JQ0KICBhcy5kYXRhLmZyYW1lKCkNCg0KDQpmaWx0ZXJlZCA8LSBncm91cGVkICU+JSBzZWxlY3QoWWVhcixHZW5yZSxBbnphaGwpDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJKYWhyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJQcm96ZW50ICUiDQoNCikNCg0KDQpmaWx0ZXJlZCAlPiUNCnBsb3RfbHkoeCA9IH5ZZWFyLCB5ID0gfkFuemFobCwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdub25lJywgc3RhY2tncm91cCA9ICdvbmUnLGdyb3Vwbm9ybSA9ICdwZXJjZW50Jyxjb2xvciA9IH5HZW5yZSAsY29sb3JzID0gbXlQYWxldHRlKSU+JSANCiAgbGF5b3V0KHRpdGxlPSJNYXJrZXRzaGFyZSBHZW5yZXZlcnNjaGllYnVuZyBpbiAlIHZvbiAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KDQpCZWltIEJldHJhY2h0ZW4gZsOkbGx0IGhpZXIgZGlyZWt0IGF1ZiwgZGFzcyBBY3Rpb24gR2FtZXMgMTk4MC0xOTg0IGVpbmVuIGdyb8OfZW4gTWFya3RhbnRlaWwsIHRlaWx3ZWlzZSBiaXMgaGluIHp1IDUwJSBhdXNnZW1hY2h0IGhhYmVuLiBEaWVzZSBiaXMgMTk5NCBhdWYgZ2VyYWRlbWFsIDMlIGFic2lua2VuIGJldm9yIGRlciBTdGV0aWdlIFdhY2hzdHVtIGJlZ2lubnQgYmlzIHNpZSAyMDE2IHdpZWRlciBiZWkgS25hcCA0MCUgZW5kZW4uIEF1Y2ggZGllIGdyb8OfZSBNYXJrdHByw6RzZW56IHZvbiBQbGF0Zm9ybSBTcGllbGVuIHp3aXNjaGVuIDE5ODQgdW5kIDE5OTIgaXN0IGd1dCBlcmtlbm5iYXIgd29oaW5nZWdlbiBSYWNpbmcgR2FtZXMgc2ljaCB6d2lzY2hlbiAxOTk0IHVuZCAyMDA0IGRlciBncsO2w590ZW4gYmVsaWVidGhlaXQgZXJmcmV1ZW4uDQoNCiMjIHstfQ0KDQpIaWVyYmVpIHp1IGVya2VubmVuIGlzdCBPYndvaGwgZGllIEFuemFobCBkZXIgSsOkaHJsaWNoZW4gU3BpZWxlcmVsZWFzZXMgw7xiZXIgZGllIEphaHJlIGhpbndlZyBzdGV0aWcgd8OkY2hzdCBibGVpYmVuIGRpZSBNZWlzdGVuIEdlbnJlcyDDpGhubGljaCB2aWVsIHZlcnRyZXRlbi4gQXVmZsOkbGxpZyBzaW5kIGhpZXJiZWkgU3RyYXRlZ3ktR2FtZXMgZGllIGVyc3QgMTk5MSBkYXMgZXJzdGUgbWFsIGF1ZnRyZXRlbSBTZWl0ZGVtIG9id29obCBzaWUgTGVpY2h0IGFuIE1hcmtldHNoYXJlIHZlcmxpZXJlbiBncm9iIGdsZWljaCBibGVpYmVuLiBBdcOfZXJkZW0gc2luZCBBY3Rpb24gR2FtZXMgZGllIFNwaWVsZSBtaXQgZGVyIHdvaGwgZ3LDtsOfdGVuIHZvbGF0aWxpdMOkdC4gU2luZCBlcyAxOTgyIG5vY2ggZmFzdCA1MCUgZGVyIEdhbWVyZWxlYXNlcyBmw6RsbHQgZGVyZW4gYXVma29tbWVuIDEwODQgc2Nob24gYXVmIG51ciBub2NoIGtuYXBwIDEwJSBhYiB1bmQgMTk4NiBzdGVpZ3QgZGVyIFdlcnQgd2llZGVyIGF1ZiBmYXN0IDMwJS4gRGllc2VyIFRyZW5kIHNldHp0IHNpY2ggZm9ydCBiaXMgMTk5NiBhYiB3ZWxjaGVtIFplaXRwdW5rdCBzaWNoIEFjdGlvbiBHYW1lcyB2b24gMy42JSDDvGJlciBkaWUgSmFocmUgYmlzIDIwMTYgYmlzIDM1JSBlbnR3aWNrZWxuLg0KDQoqKioNCg0KIyBHZW5yZWVudHdpY2tsdW5nIGltIGxhdWZlIGRlciBKYWhyZSBuYWNoIFZlcmthdWZzemFobGVuIHsjR2VucmVTYWxlc1BlclllYXJ9DQoNClNjaGF1ZW4gd2lyIHVucyBhbiB3aWUgc2ljaCBkaWUgdmVya8OkdWZlIGVudHdpY2tlbHQgaGFiZW4uIEhpZXJ6dSB2ZXJ3ZW5kZW4gd2lyIGRpZSBnbGVpY2hlbiBEaWFncmFtbWUgd2llIGJlcmVpdHMgYmVpIGRlciBCZXRyYWNodHVuZyBkZXIgU3BpZWxlIEFuemFobC4gRWluZSBlcmtsw6RydW5nIGRlciBlcnN0ZWxsdW5nIGRlciBEaWFncmFtbWUgZ2lidCBlcyBbaGllcl0oI0dlbnJlQW1vdW50UGVyWWVhcikuDQoNCiMjIFZlcmvDpHVmZSBwcm8gSmFociB7LnRhYnNldH0NCg0KIyMjIExpbmVzDQpgYGB7ciBwbG90KFNhbGVzQnlHZW5yZWJ5WWVhcjEpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyLCBHZW5yZSkgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoZ3Jfc3VtID0gc3VtKEdsb2JhbF9TYWxlcykpICU+JSBmaWx0ZXIoWWVhciE9J04vQScpJT4lZmlsdGVyKFllYXIhPTIwMjApICU+JSBmaWx0ZXIoWWVhciE9JzIwMTcnKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsR2VucmUsZ3Jfc3VtKQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJKYWhyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJWZXJrw6R1ZmUgKGluIG1pbykiDQoNCikNCg0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KCkgJT4lIA0KICBhZGRfbGluZXMoeD1+WWVhciwNCiAgICAgICAgICAgeT1+Z3Jfc3VtLCBjb2xvcj1+R2VucmUgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlZlcmthdWZzemFobGVuIGRlciBTcGllbGVyZWxlYXNlcyB2b24gMTk4MC0yMDE2IiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCmBgYA0KDQpCZWltIGVyc3RlbiBCZXRyYWNodGVuICBmw6RsbHQgaGllciBkaXJla3QgZGllIGhvaGUgdm9sYXRpbGl0w6R0IGRlciBlaW56ZWxuZW4gR3JhcGhlbiBhdWYsIHdlbGNoZXMgZHVyY2ggZGVuIGhvaGVuIEVpbmZsdXNzIGVpbmlnZXIgZ3V0bGF1ZmVuZGVyIEdhbWVzIGF1ZiBkaWUgVmVya2F1ZnN6YWhsZW4genVyw7xja3p1ZsO8aHJlbiBpc3QuIEFtIGVpbmZhY2hzdGVuIGlzdCBkaWVzIHp3aXNjaGVuIDE5ODAgdW5kIDE5OTIgZXJrZW5uYmFyLiAxOTgxIGlzdCBlaW4gc3Bpa2UgaW4gQWN0aW9uIEdhbWVzIGVya2VubmJhciwgbmFtZXRsaWNoIGR1cmNoIGRpZSB2ZXLDtmZmZW50bGljaHVuZyBuYW1lbnRsaWNoZXIgc3BpZWxlIHdpZSBGcm9nZ2VyIHVuZCBQaXRmYWxsLiBJbSBKYWhyIDE5ODQgZXJrZW5uYmFyIGlzdCBkYW5uIGRlciBzcGlrZSB2b24gU2hvb3Rlcm4gZHVyY2ggRHVjay1HYW1lIHNvd2llIFBsYXRmb3JtIGdhbWVzIGluIDE5ODUgZHVyY2ggU3VwZXIgTWFyaW8gQnJvcy4gU3VwZXIgTWFyaW8gcHLDpGd0IGRpZSBIaXN0b3JpZSBkZXIgUGxhdGZvcm0gR2FtZXMgYXVjaCB6d2lzY2hlbiAxOTg4IHVuZCAxOTkwIG1pdCBTdXBlciBNYXJpbyBCcm9zIDMgdW5kIFN1cGVyIE1hcmlvIFdvcmxkLiBEYXMgU3BpZWwgd2VsY2hlcyAxOTg5IGVpbmVuIGF1c3NjaGxhZyBkZXIgUHV6emxlLUdhbWVzIHZlcnVyc2FjaHQgZMO8cmZ0ZSBzb2dhciBMZXNlcm4sIHdlbGNoZSBuaWNodCBUZWlsIGRlciBHYW1pbmctQ29tbXVuaXR5IHNpbmQgZWluIGJlZ3JpZmYgc2VpbjogVGV0cmlzLg0KDQojIyMgRmlsbGVkIExpbmVzDQoNCmBgYHtyIHBsb3QoU2FsZXNCeUdlbnJlYnlZZWFyMiksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGdyb3VwX2J5KFllYXIsIEdlbnJlKSAlPiUNCiAgZHBseXI6OnN1bW1hcml6ZShncl9zdW0gPSBzdW0oR2xvYmFsX1NhbGVzKSkgJT4lIGZpbHRlcihZZWFyIT0nTi9BJyklPiVmaWx0ZXIoWWVhciE9MjAyMCkgJT4lIGZpbHRlcihZZWFyIT0nMjAxNycpICU+JQ0KICBhcy5kYXRhLmZyYW1lKCkNCg0KDQpmaWx0ZXJlZCA8LSBncm91cGVkICU+JSBzZWxlY3QoWWVhcixHZW5yZSxncl9zdW0pDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkphaHIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlZlcmvDpHVmZSAoaW4gbWlvKSINCg0KKQ0KDQoNCmZpbHRlcmVkICU+JQ0KcGxvdF9seSh4ID0gflllYXIsIHkgPSB+Z3Jfc3VtLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ25vbmUnLCBmaWxsID0gJ3RvemVyb3knLGNvbG9yID0gfkdlbnJlICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJWZXJrYXVmc3phaGxlbiBkZXIgU3BpZWxlcmVsZWFzZXMgdm9uIDE5ODAtMjAxNiIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KDQpgYGANCg0KRHVyY2ggQmV0cmFjaHRlbiBkZXMgRmlsbGVkIExpbmUgUGxvdHMgZXJrZW5uZW4gd2lyIGd1dCBkZW4gSG9jaCBkZXIgU3RyYXRlZ2llc3BpZWxlIGltIEphaHIgMTk5OSBkdXJjaCBzcGllbGUgd2llIFBva2Vtb24gU3RhZGl1bSwgV2Fyem9uZSAyMTAwIG9kZXIgQWdlIG9mIEVtcGlyZXMgSUkuIEF1Y2ggZGllIFNwaWtlcyBkZXIgUm9sZS1QbGF5aW5nIEdhbWVzIGltIGdsZWljaGVuIEphaHIgZHVyY2ggUG9rZW1vbiBHb2xkL1NpbGJlciB1bmQgRmluYWwgRmFudGFzeSBWSUlJIHNvd2llIDE5OTYgZHVyY2ggUG9rZW1vbiBSb3QvQmxhdSBzaW5kIGRldXRsaWNoIGVya2VubmJhci4NCg0KIyMjIFN0YWNrZWQgTGluZXMgey5hY3RpdmV9DQoNCmBgYHtyIHBsb3QoU2FsZXNCeUdlbnJlYnlZZWFyMyksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGdyb3VwX2J5KFllYXIsIEdlbnJlKSAlPiUNCiAgZHBseXI6OnN1bW1hcml6ZShncl9zdW0gPSBzdW0oR2xvYmFsX1NhbGVzKSkgJT4lIGZpbHRlcihZZWFyIT0nTi9BJyklPiVmaWx0ZXIoWWVhciE9MjAyMCkgJT4lIGZpbHRlcihZZWFyIT0nMjAxNycpICU+JQ0KICBhcy5kYXRhLmZyYW1lKCkNCg0KDQpmaWx0ZXJlZCA8LSBncm91cGVkICU+JSBzZWxlY3QoWWVhcixHZW5yZSxncl9zdW0pDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkphaHIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlZlcmvDpHVmZSAoaW4gbWlvKSINCg0KKQ0KDQoNCmZpbHRlcmVkICU+JQ0KcGxvdF9seSh4ID0gflllYXIsIHkgPSB+Z3Jfc3VtLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ25vbmUnLCBzdGFja2dyb3VwID0gJ29uZScsY29sb3IgPSB+R2VucmUgLGNvbG9ycyA9IG15UGFsZXR0ZSklPiUgDQogIGxheW91dCh0aXRsZT0iVmVya2F1ZnN6YWhsZW4gZGVyIFNwaWVsZXJlbGVhc2VzIHZvbiAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KDQpTdGFja2VkIExpbmVzIHNpbmQgdmVybXV0bGljaCBkYXMgQmVzdGUgRGlhZ3JhbW0gdW0gVmVya2F1ZnN6YWhsZW4gbWl0IGRlciBBbnphaGwgenUgdmVyZ2xlaWNoZW4uIEFtIGF1ZmbDpGxsaWdzdGVuIGhpZXIgc2luZCwgZGFzcyBkaWUgVm9sYXRpbGl0w6R0IGluIGRlbiBmcsO8aGVyZW4gSmFocmVuICgxOTgwLTE5OTUpIGJlaSBnZXJpbmdlcmVyIHByw6RzZW56IHZvbiBWaWRlb3NwaWVsZW4gZGV1dGxpY2ggZ3LDtsOfZXIgYXVzZsOkbGx0IGFscyBpbiBkZXIgYW56YWhsIGRlciBWaWRlb3NwaWVsZS4gSW4gZGVuIFNww6R0ZXJlbiBKYWhyZW4gdm9yYWxsZW0gYWIgMjAwMyBmYWxsZW4gZGllIFNjaHdhbmt1bmdlbiBoaWVyIGplZG9jaCBkZXV0bGljaCBnZXJpbmdlciBhdXMsIHdhcyB2ZXJtdXRsaWNoIGFuIGRlciBow7ZoZXJlbiBNYXNzZSB2b24gVmlkZW9zcGllbGVuIHVuZCBkYW1pdCBlaW5lbSBicmVpdCBnZWbDpGNoZXJ0ZXJlbSBOdXR6ZXJpbnRlcmVzc2UgbGllZ3QuDQoNCiMjIyBHZW5yZXZlcnNjaGllYnVuZw0KDQpgYGB7ciBwbG90KFNhbGVzQnlHZW5yZWJ5WWVhcjQpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyLCBHZW5yZSkgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoZ3Jfc3VtID0gc3VtKEdsb2JhbF9TYWxlcykpICU+JSBmaWx0ZXIoWWVhciE9J04vQScpJT4lZmlsdGVyKFllYXIhPTIwMjApICU+JSBmaWx0ZXIoWWVhciE9JzIwMTcnKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsR2VucmUsZ3Jfc3VtKQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJKYWhyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJQcm96ZW50ICUiDQoNCikNCg0KDQpmaWx0ZXJlZCAlPiUNCnBsb3RfbHkoeCA9IH5ZZWFyLCB5ID0gfmdyX3N1bSwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdub25lJywgc3RhY2tncm91cCA9ICdvbmUnLGdyb3Vwbm9ybSA9ICdwZXJjZW50Jyxjb2xvciA9IH5HZW5yZSAsY29sb3JzID0gbXlQYWxldHRlKSU+JSANCiAgbGF5b3V0KHRpdGxlPSJNYXJrZXRzaGFyZSBHZW5yZXZlcnNjaGllYnVuZyBpbiAlIHZvbiAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KDQpEdXJjaCBkaWUgaG9oZSBWb2xhdGlsaXTDpHQgaXN0IGRpZSBHcmFmaWsgaW4gZGVuIGZyw7xoZXJlbiBKYWhyZW4gdm9yYWxsZW0gendpc2NoZW4gMTk4MCB1bmQgMTk5MiBzZWhyIGR1cmNoZWluYW5kZXJuIHVuZCBUZWlsd2Vpc2UgcmVjaHQgc2Nod2llcmlnIHp1IGxlc2VuLiBJbiBkZW4gZGFyYXVmIGZvbGdlbmRlbiBKYWhyZW4gaXN0IGVzIGFiZXIgZGV1dGxpY2ggbGVpY2h0ZXIgYmVzdGltbXRlIGRpbmdlIHdpZSBkYXMgZXJzdG1hbGlnZSBhdWZ0cmV0ZW5zIGRlciBTdHJhdGVnaWVzcGllbGUgMTk5MiBvZGVyIGRpZSBmYXN0IFZvbGxzdMOkbmRpZ2UgQWJzdGluZW56IHZvbiBQdXp6bGUgR2FtZXMgendpc2NoZW4gMTk5NSB1bmQgMjAwMiBzb3dpZSBhYiAyMDEyIHp1IGVya2VubmVuLg0KDQojIyB7LX0NCg0KV2llIHp1IGVyd2FydGVuIGzDpHNzdCBzaWNoIGhpZXIgZWluIEdyb8OfZXIgb3ZlcmxhcCB6dSBkZW4gQW56YWhsIGRlciBHYW1lcmVsZWFzZXMgZmVzdHN0ZWxsZW4gZXMga2FubiBqZWRvY2ggZWluZSBIb2hlIFZvbGl0aWxpdMOkdCBkdXJjaCBlaW56ZWxuZSBTcGllbGVyZWxlYXNlcyB2b3JhbGxlbSBpbiBmcsO8aGVyZW4gSmFocmVuIGZlc3RnZXN0ZWxsdCB3ZXJkZW4uIERpZXMgaGF0IGRlbiBHcnVuZCBkYXMgZWluaWdlICJLYXNzZW5zY2hsYWdlciIgaGllciBlaW5lbiBncm/Dn3RlaWwgZGVzIE1hcmt0ZXMgYXVzbWFjaGVuIHVuZCBpaG4gc29taXQgc3RhcmsgYmVlaW5mbHVzc2VuLiBBbnp1bWVya3RlbiBpc3QgamVkb2NoIGRhcyBTcGllbGUgZ2VybmUgUmVyZWxlYXN0IHdlcmRlbiB2b3JhbGxlbSBhdWYgdW50ZXJzY2hpZWRsaWNoZW4gS29uc29sZW4sIGRpZXMgaW4gdW5zZXJlbSBEYXRlbnNhdHogamVkb2NoIG5pY2h0IHp1c2FtbWVnZWbDvGhydCB3aXJkLiBXZWl0ZXJlcyBoaWVyenUgaW0gW0Zheml0XSgjQXVmZ2V0cmV0ZW5lUHJvYmxlbWUpDQoNCioqKg0KDQojIEdlbnJlZW50d2lja2x1bmcgaW0gbGF1ZmUgZGVyIEphaHJlIG5hY2ggVmVya2F1ZnN6YWhsZW4gcHJvIFNwaWVsIHsjR2VucmVTYWxlc1BlckdhbWVQZXJZZWFyfQ0KDQpOYWNoZGVtIHdpciBudW4gQW5hbHlzaWVydCBoYWJlbiB3aWUgc2ljaCBkaWUgQW56YWhsIGRlciBTcGllbGVyZWxlYXNlcyBzb3dpZSBkaWUgVmVya2F1ZnN6YWhsZW4gZW50d2lja2VsdCBoYWJlbiB3w6RyZSBlcyBkb2NoIGludGVyZXNzYW50IGJlaWRlcyBnZWdlbsO8YmVyenVzdGVsbGVuIHVuZCBkaXJla3QgenUgdmVyZ2xlaWNoZW4uIEhpZXJ6dSB2ZXJ3ZW5kZW4gd2lyIGVybmV1dCBkaWUgYmVyZWl0cyBiZWthbm50ZW4gW0RpYWdyYW1tZV0oI0dlbnJlQW1vdW50UGVyWWVhcikgbnV0emVuIGplZG9jaCBpbiBkZXIgKmRwbHlyOjpzdW1tYXJpemUoKSogZnVua3Rpb24gZGllIFN1bW1lIGRlciBWZXJrYXVmc3phaGxlbiB3ZWxjaGUgd2lyIGR1cmNoIGRpZSBBbnphaGwgZGVyIEVpbnRyw6RnZSB0ZWlsZW4uDQoNCiMjIFZlcmvDpHVmZSBwcm8gU3BpZWwgcHJvIEphaHIgey50YWJzZXR9DQoNCiMjIyBMaW5lcw0KYGBge3IgcGxvdChTYWxlc1BlckdhbWVQZXJHZW5yZWJ5WWVhcjEpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyLCBHZW5yZSkgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoZ3Jfc3VtID0gc3VtKEdsb2JhbF9TYWxlcykvbigpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLEdlbnJlLGdyX3N1bSkNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkphaHIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlZlcmvDpHVmZSBwcm8gU3BpZWwiDQoNCikNCg0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KCkgJT4lIA0KICBhZGRfbGluZXMoeD1+WWVhciwNCiAgICAgICAgICAgeT1+Z3Jfc3VtLCBjb2xvcj1+R2VucmUgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlZlcmvDpHVmZSBwcm8gU3BpZWwgbmFjaCBHZW5yZSB2b24gMTk4MC0yMDE2IiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCmBgYA0KDQpJbSBMaW5lcy1QbG90IGVya2VubmVuIHdpciBkaXJla3QgZGllIGluIGRlciBbVmVya2F1ZnN6YWhsYW5hbHlzXSgjR2VucmVTYWxlc1BlclllYXIpIGdlbmFubnRlbiBFeHRyZW1lIHdlbGNoZSBkdXJjaCBlaW56ZWxuZSBTcGllbGUsIHZvcmFsbGVtIGluIGRlbiBmcsO8aGVyZW4gSmFocmVuLCBiZWVpbmZsdXNzdCB3ZXJkZW4uIEFtIGRldXRsaWNoc3RlbiBpc3QgZGllcyBpbiBTaG9vdGVyIEdhbWVzIDE5ODQgZHVyY2ggRHVjay1HYW1lIHVuZCBQbGF0Zm9ybSBzcGllbGUgMTk4NSBkdXJjaCBTdXBlciBNYXJpbyBCcm9zLiBBdWNoIFRldHJpcyAoUHV6emxlIDE5ODkpIHNvd2llIFN1cGVyIE1hcmlvIEJyb3MgMyAoUGxhdGZvcm0gMTk4OCkgdW5kIFN1cGVyIE1hcmlvIFdvcmxkIChQbGF0Zm9ybSAxOTkwKSBzaW5kIGRldXRsaWNoIGVya2VubmJhci4gTmV1IGVya2VubmJhciBpc3QgaGllciBkZXIgQXVzc2NobGFnIGluIFJhY2luZyBnYW1lcyAxOTkyIGR1cmNoIGRlbiBLbGFzc2lrZXIgU3VwZXIgTWFyaW8gS2FydCB3ZXNzZW4gTmFjaGZvbGdlciBiaXMgaGV1dGUgYXVmIGZhc3QgamVkZXIgTmludGVuZG8gS29uc29sZSB2ZXLDtmZmZW50bGljaHQgd3VyZGVuLg0KDQojIyMgRmlsbGVkIExpbmVzIHsuYWN0aXZlfQ0KDQpJbiBkZW0gRmFsbCBkZXIgVmVya8OkdWZlIFBybyBKYWhyIHNpbmQgZGllIFN0YWNrZWQgTGluZXMgbGVpZGVyIHdlbmlnIGF1c3NjaGxhZ2dlYmVuZCB1bmQgZGFoZXIgYXVjaCBuaWNodCBhbHMgZXJzdGUgYW5zaWNodCB2b3JhdXNnZXfDpGhsdC4gWnVtIHZlcnN0ZWhlbiBkZXIgQW5hbHlzZSBzb2xsdGUgamVkb2NoIGRlciBMaW5lcy1UYWIgenVlcnN0IGdlbGVzZW4gd2VyZGVuLg0KDQpgYGB7ciBwbG90KFNhbGVzUGVyR2FtZVBlckdlbnJlYnlZZWFyMiksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGdyb3VwX2J5KFllYXIsIEdlbnJlKSAlPiUNCiAgZHBseXI6OnN1bW1hcml6ZShncl9zdW0gPSBzdW0oR2xvYmFsX1NhbGVzKS9uKCkpICU+JSBmaWx0ZXIoWWVhciE9J04vQScpJT4lZmlsdGVyKFllYXIhPTIwMjApICU+JSBmaWx0ZXIoWWVhciE9JzIwMTcnKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsR2VucmUsZ3Jfc3VtKQ0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiSmFociINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiVmVya8OkdWZlIHBybyBTcGllbCINCg0KKQ0KDQpmaWx0ZXJlZCAlPiUNCnBsb3RfbHkoeCA9IH5ZZWFyLCB5ID0gfmdyX3N1bSwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdub25lJywgZmlsbCA9ICd0b3plcm95Jyxjb2xvciA9IH5HZW5yZSAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iVmVya8OkdWZlIHBybyBTcGllbCBuYWNoIEdlbnJlIHZvbiAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCg0KYGBgDQoNCkJlaW0gQmV0cmFjaHRlbiBkZXIgRmlsbGVkLUxpbmVzIGbDpGxsdCBhdWYgZGFzIG5lYmVuIGRlbiBCZXJlaXRzIGdlbmFubnRlbiBFeHRyZW1lbiBSYWNpbmcgZ2FtZXMgYXVjaCBpbSBKYWhyZSAxOTkwIHNjaG9uIGVpbmVuIEhvY2hwdW5rdCBkdXJjaCBGLTEgUmFjZSBlcmZ1aHIuIEF1Y2ggZGFzIEV4dHJlbSBkZXMgQWN0aW9uIGdlbnJlcyAxOTg3IGR1cmNoIFplbGRhIElJOiBUaGUgQWR2ZW50dXJlIG9mIExpbmsgaXN0IGhpZXIgZGV1dGxpY2hlciBlcmtlbm5iYXIuDQoNCiMjIyBTdGFja2VkIExpbmVzIA0KDQpgYGB7ciBwbG90KFNhbGVzUGVyR2FtZVBlckdlbnJlYnlZZWFyMyksZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoWWVhciwgR2VucmUpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKGdyX3N1bSA9IHN1bShHbG9iYWxfU2FsZXMpL24oKSkgJT4lIGZpbHRlcihZZWFyIT0nTi9BJyklPiVmaWx0ZXIoWWVhciE9MjAyMCkgJT4lIGZpbHRlcihZZWFyIT0nMjAxNycpICU+JQ0KICBhcy5kYXRhLmZyYW1lKCkNCg0KDQpmaWx0ZXJlZCA8LSBncm91cGVkICU+JSBzZWxlY3QoWWVhcixHZW5yZSxncl9zdW0pDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJKYWhyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJWZXJrw6R1ZmUgcHJvIFNwaWVsIg0KDQopDQoNCmZpbHRlcmVkICU+JQ0KcGxvdF9seSh4ID0gflllYXIsIHkgPSB+Z3Jfc3VtLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ25vbmUnLCBzdGFja2dyb3VwID0gJ29uZScsY29sb3IgPSB+R2VucmUsIGNvbG9ycyA9IG15UGFsZXR0ZSklPiUgDQogIGxheW91dCh0aXRsZT0iVmVya8OkdWZlIHBybyBTcGllbCBuYWNoIEdlbnJlIHZvbiAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KDQpTdGFja2VkIExpbmVzIGlzdCBoaWVyIGbDvHIgZWluZSBBbmFseXNlIGRlciBlaW56ZWxuZW4gU3BpZWxlZ2VucmVzIGxlaWRlciBuaWNodCBoaWxmcmVpY2guIERlciBhdWZtZXJrc2FtZSBCZW9iYWNodGVyIHdpcmQgc2ljaCBqZWRvY2ggYW4gZWluZSBkZXIgZXJzdGVuIEdyYWZpa2VuIGVyaW5uZXJuIGluIGRlbmVuIHdpciBbZGllIFNhbGVzIHBybyBHYW1lXSgjVmlkZW9HYW1lUmVsZWFzZXMpIGFuYWx5c2llcnQgaGFiZW4gdW5kIHNpY2ggRnJhZ2VuIHdhcnVtIGRpZSBXZXJ0ZSBoaWVyIGRldXRsaWNoIGjDtmhlciBhdXNmYWxsZW4gYWxzIG5vY2ggYmV2b3IuIFdhciBpbiBkZXIgQW5hbHlzZSBvaG5lIEdlbnJlcyBkZXIgTWF4aW1hbHdlcnQgbm9jaCBiZWkgNCBzbyBpc3QgZXIgSGllciBiZWkgbWVociBhbHMgMjAuIERpZXMgbGllZ3Qgdm9yYWxsZW0gZGFyYW4sIGRhc3MgQWN0aW9uIGdhbWVzIGluIGRlbiBGcsO8aGVyZW4gSmFocmVuIGVpbmVuIGdyb8OfdGVpbCBkZXIgUmVsZWFzZXMgYXVzbWFjaGVuIGJlaSBkZW4gdmVya2F1ZnN6YWhsZW4gYWJlciBlaGVyIGdlcmluZyBhdXNmYWxsZW4gdW5kIGRlbiBkdXJjaHNjaG5pdHQgZGFoZXIgaGVydW50ZXJ6aWVoZW4uIFNpbmQgZGllIFNwaWVsZSBuYWNoIEdlbnJlIGF1ZmdldGVpbHQgYmVlaW5mbHVzc3QgZGFzIHNjaGxlY2h0IHBlcmZvcm1lbmRlIEFjdGlvbiBHZW5yZSBkaWUgVmVya2F1ZnN6YWhsZW4gcHJvIFNwaWVsIGRlciBhbmRlcmVuIGplZG9jaCBuaWNodCB1bmQgc28gZXJoYWx0ZW4gd2lyIGFkZGl0aXYgZWluZSBkZXV0bGljaCBncsO2w59lcmUgWmFobCBhbHMgenV2b3IuDQoNCiMjIyBHZW5yZXZlcnNjaGllYnVuZyANCg0KYGBge3IgcGxvdChTYWxlc1BlckdhbWVQZXJHZW5yZWJ5WWVhcjQpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyLCBHZW5yZSkgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoZ3Jfc3VtID0gc3VtKEdsb2JhbF9TYWxlcykvbigpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLEdlbnJlLGdyX3N1bSkNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkphaHIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlByb3plbnQgJSINCg0KKQ0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KHggPSB+WWVhciwgeSA9IH5ncl9zdW0sIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbm9uZScsIHN0YWNrZ3JvdXAgPSAnb25lJyxncm91cG5vcm0gPSAncGVyY2VudCcsY29sb3IgPSB+R2VucmUsIGNvbG9ycyA9IG15UGFsZXR0ZSklPiUgDQogIGxheW91dCh0aXRsZT0iTWFya2V0c2hhcmUgaW4gVmVya8OkdWZlIHBybyBTcGllbCBuYWNoIEdlbnJlIHZvbiAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KDQpEdXJjaCBkaWUgaG9oZSB2b2xhdGlsaXTDpHQgaW4gZGVuIEZyw7xoZXJlbiBKYWhyZW4gaXN0IGF1Y2ggaGllciB3aWUgYmVpIGRlbiBWZXJrYXVmc3phaGxlbiBkYXMgR2VucmVzaGlmdCBEaWFncmFtbSB3ZW5pZyBhdXNzY2hsYWdnZWJlbmQuIEFCIDE5OTQga2FubiBtYW4gamVkb2NoIGRldXRsaWNoIGVya2VubmVuIHdpciBzaWNoIGRpZSBHZW5yZXMgaW0gbGF1ZmUgZGVyIEphaHJlIGVudHdpY2tlbG4uIFNob290ZXIgd2VyZGVuIGRldXRsaWNoIGJlbGllYnRlciB3b2hpbmdlZ2VibiBSb2xlLVBsYXlpbmcgZ2FtZXMgYXVmIGRlbSBhYnN0ZWlnZW5kZW4gQXN0IHNpbmQuDQoNCiMjIHstfQ0KDQpBdWNoIGhpZXIgaXN0IHdpZSBlcndhcnRldCBkaWUgRW50d2lja2x1bmcgUHJvemVudHVhbCDDpGhubGljaC4gQXVmZsOkbGxpZyBpc3QgamVkb2NoIGRhcyBTaG9vdGVyIHRyb3R6IGlocmVyIGdlcmluZ2VuIFZlcnRyZXR1bmcgaW4gZGVyIFByb3plbnR1YWxlbiBWZXJ0ZWlsdW5nIDE5ODQgc293aWUgMjAxNCwyMDE1IHVuZCAyMDE2IGRpZSBOYXNlIFZvcm5lIGhhYmVuLiBQbGF0Zm9ybSBHYW1lcyBoYWJlbiAxOTg1LDE5ODggdW5kIDE5OTAgZGllIE5hc2UgVm9ybmUuIERpZSBIb2NoemVpdCBkZXIgUHV6emxlIEdhbWVzIHNpbmQgdW5hbmdlZm9jaHRlbiAxOTg4IG1pdCBkZW0gV2VsdHdlaXRiZWthbm50ZW4gdW5kIGF1ZiBQbGF0eiA2IGRlciBtZWlzdHZlcmthdWZ0ZW4gdmlkZW9zcGllbGU6IFRldHJpcy4gQXVmZsOkbGxpZyBzaW5kIHZvcmFsbGVtIGRpZSBNb2Rlcm5lcmVuIGVudHdpY2tsdW5nZW4uIFNpbmQgaW4gZGVuIDE5OTYtMjAwNWVyIEphaHJlbiBSb2xlLVBsYXlpbmcgdW5kIHNvbWl0IGxhbmdzYW1lIGltbWVyc2l2ZSBlcmxlYm5pc3NlIG5vY2ggZGV1dGxpY2ggQmVsaWVidGVyIGhhYmVuIGhldXR6dXRhZ2UgU2hvb3RlciBtaXQgaWhyZW0gUnVuZGVuYmFzaWVydGVtLCAiRmFzdCBQYWNlZCIgYWxzbyBzY2huZWxsZW0gc3BpZWxmbHVzcyBkaWUgTmFzZSBWb3JuZS4gSW4gZGVyIE1vZGVybmVuIFdlbHQgaXN0IGVzIGRldXRsaWNoIGVpbmZhY2hlciB1bmQgZsO8ciBWaWVsZSBsZXV0ZSB3ZW5pZ2VyIFplaXRpbnRlbnNpdiBrdXJ6IGVpbmUgUnVuZGUgdm9uIDE1LTQ1IG1pbnV0ZW4genUgc3BpZWxlbiBhbHMgc2ljaCBTdHVuZGVubGFuZyBpbiBlaW5lIFJvbGxlIGhpbmVpbnp1dmVyc2V0emVuLiBWaWVsZW4gTWVuc2NoZW4gZmVobHQgZWluZmFjaCBaZWl0IG9kZXIgR2VkdWxkIHVtIHNpY2ggaW4gZGVyIFplaXQgdm9uIG1vZGVybmVuIE1lZGllbiB3aWUgVGlrLVRvayBvZGVyIEluc3RhZ3JhbW0sIHdlbGNoZSBzaWNoIGF1ZiBrdXJ6ZSBlcmxlYm5pc3NlIHZvbiBvZnQgd2VuaWdlbiBTZWt1bmRlbiBzcGV6aWFsaXNpZXJ0IGhhYmVuLCBpbiBlaW4gSW1tZXJzaXZlcyBlcmxlYm5pcyBoZXJlaW56dXZlcnNldHplbi4NCg0KKioqDQoNCiMgR2VucmV2ZXJ0ZWlsdW5nIG5hY2ggUHVibGlzaGVyIHsjR2VucmVCeVB1Ymxpc2hlckdsb2JhbH0gIA0KDQpEYSB3aXIgbnVuIHNvd29obCBHZW5yZXMgYWxzIGF1Y2ggUHVibGlzaGVyIGJldHJhY2h0ZXQgaGFiZW4gd8OkcmUgZXMgZG9jaCBkZXIgZWluemlnIGxvZ2lzY2hlIHNjaHJpdHQgZGllc2UgYmVpZGVuIERhdGVuIHp1c2FtbWVuenVmw7xocmVuIHVuZCB6dSB2ZXJnbGVpY2hlbi4gR2lidCBlcyBoaWVyIFB1Ymxpc2hlciBkaWUgdmVyc2NoaWVkZW5lIEdlbnJlcyBiZXZvcnp1Z2VuIGJ6dy4gZGVyZW4gQmVzdHNlbGxlciBzaWNoIGluIGJlc3RpbW10ZW4gR2VucmVzIFR1bW1lbG4/DQoNCkhpZXJ6dSB2ZXJ3ZW5kZW4gd2lyIGVpbiBzdGFja2VkIEJhci1QbG90LiBEZXIgYmVnaW5uIGRlciBEaWFncmFtbWVyc3RlbGx1bmcgaXN0IGhpZXJiZWkgw6RobmxpY2ggd2llIG5vY2ggYmVpIFtQYXJldG9kaWFncmFtbWVuXSgjUGxhdGZvcm1hbmFseXNlKS4gUmVsYXRpdiBzY2huZWxsIGbDpGxsdCBoaWVyIGplZG9jaCBhdWYgZGFzIHdpciBhbnN0YXR0IG51ciBlaW5lcyBEYXRhZnJhbWVzIFp3ZWkgUHJvZHV6aWVyZW4uIFp1bSBlaW5lbiBkZXIgYmVyZWl0cyBiZWthbm50ZSAqZ3JvdXBlZCogRGF0YWZyYW1lIHdlbGNoZXIgUHVibGlzaGVyLCBHZW5yZSB1bmQgVmVya2F1ZnN6YWhsZW4gZWJlbmplbmVyIEdlbnJlcyBiZWluaGFsdGV0LiBadW0gYW5kZXJlbiAqUHVibGlzaGVyU2FsZXMqIHdlbGNoZXIgZWluZSBMaXN0ZSBkZXIgUHVibGlzaGVyIG1pdCBHZXNhbXR2ZXJrYXVmc3phaGxlbiB2b24gbWVociBhbHMgMzAwIG1pbyBlbnRow6RsdC4gRGllc2VuIHZlcndlbmRlbiB3aXIgaW0gd2VpdGVyZW4gdmVybGF1ZiB1bSBhdXMgdW5zZXJlbSAqZ3JvdXBlZCogRGF0ZW5zYXR6IGFsbGUgUHVibGlzaGVyIHp1IGVudGZlcm5lbiBkaWUgc2ljaCBuaWNodCBpbiAqUHVibGlzaGVyU2FsZXMqIGJlZmluZGVuLiBEYXMgZ2VzY2hpZWh0IG1pdCBoaWxmZSBkZXMgKmZpbHRlcigpKiBjb21tYW5kcyB1bmQgZGVtIFNjaGxhZ3dvcnQgKiVpbiUqLiBEZXIgcmVzdCBkZXIgRGlhZ3JhbW1lcnN0ZWxsdW5nIHZlcmjDpGx0IHNpY2ggZXF1aXZhbGVudCB6dXIgW1B1Ymxpc2hlcmFuYWx5c2VdKCNQdWJsaXNoZXJSZWxlYXNlcykgbWl0IGRlbSB1bnRlcnNjaGllZCBkYXMgZGllIEJhcnMgYmVpIGRlciBEaWFncmFtbWVyc3RlbGx1bmcgbmljaHQgc29ydGllcnQgd2VyZGVuLg0KDQoNCiMjIEdlbnJldmVydGVpbHVuZyBwcm8gUHVibGlzaGVyIHsudGFic2V0fQ0KDQojIyMgVmVya8OkdWZlDQoNCmBgYHtyIHBsb3QoU2FsZXNHZW5yZWJ5UHVibGlzaGVyKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyLEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApIA0KDQpQdWJsaXNoZXJTYWxlcyA8LSBncm91cGVkICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkgJT4lIGZpbHRlcihHbG9iYWxfU2FsZXM+MzAwKQ0KDQpncm91cGVkIDwtIGdyb3VwZWQgJT4lIGZpbHRlcihQdWJsaXNoZXIgJWluJSBQdWJsaXNoZXJTYWxlcyRQdWJsaXNoZXIpDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQoNCmdyb3VwZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwoZ3JvdXBlZCRQdWJsaXNoZXIsICJFbnRlcnRhaW5tZW50IikNCmdyb3VwZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwoZ3JvdXBlZCRQdWJsaXNoZXIsICJJbnRlcmFjdGl2ZSIpDQpncm91cGVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKGdyb3VwZWQkUHVibGlzaGVyLCAiU3R1ZGlvcyIpDQpncm91cGVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKGdyb3VwZWQkUHVibGlzaGVyLCAiR2FtZXMiKQ0KZ3JvdXBlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChncm91cGVkJFB1Ymxpc2hlciwgIkdhbWUiKQ0KDQogIA0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJHZW5yZSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiVmVya8OkdWZlIChpbiBtaW8pIg0KDQopDQoNCmdyb3VwZWQlPiUNCiAgcGxvdF9seSh4PX5QdWJsaXNoZXIsDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgIHR5cGU9J2JhcicsDQogICAgICAgICAgIGNvbG9yPX5HZW5yZSwgY29sb3JzID0gbXlQYWxldHRlKSAgJT4lIA0KICBsYXlvdXQodGl0bGU9IlZlcmvDpHVmZSBwcm8gR2VucmUgcHJvIFB1Ymxpc2hlciIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheSwNCiAgICAgICAgIGJhcm1vZGUgPSAnc3RhY2snDQogICAgICAgICApDQoNCg0KYGBgDQoNCkJlaW0gQmV0cmFjaHRlbiBkZXIgVmVya2F1ZnN6YWhsZW4gZsOkbGx0IGRpcmVrdCBhdWYsIGRhc3MgZGllIG1laXN0ZW4gUHVibGlzaGVyIGJlc3RpbW10ZSBHZW5yZXMgcHLDpGZlcmllcmVuLiBBY3RpdmlzaW9uIGhhYmVuIG1pdCBDYWxsIG9mIER1dHkgZWluZW4gZ3Jvw590ZWlsIGlocmVyIHZlcmvDpHVmZSBpbSBTaG9vdGVyIEdlbnJlLiBEYXMgRWxlY3Ryb25pYyBBcnRzIG1pdCBGSUZBIHVuZCBNYWRkZW5ORkwgaW0gU3BvcnQgR2VucmUgYnJlaXQgdmVydHJldGVuIHNpbmQgaXN0IHdlbmlnIFZlcnd1bmRlcmxpY2guIFNob290ZXJuIChCYXR0bGVmaWVsZCkgdW5kIFJhY2luZyAoTmVlZCBmb3IgU3BlZWQpIHNpbmQgamVkb2NoIGF1Y2ggc2VociBCZWxpZWJ0ZSBHZW5yZXMgYmVpIGRlbSBVUy1iYXNpZXJ0ZW0gR2FtaW5nIHJpZXNlbi4gTmludGVuZG8gc3BlemlmaXppZXJ0IHNpY2ggd2VuaWcgVmVyd3VuZGVybGljaCBhdWYgUGxhdGZvcm0gKFN1cGVyIE1hcmlvKSB1bmQgUm9sZS1QbGF5aW5nKFBva2Vtb24pLiBTb255IGhpbmdlZ2VuIGbDpGNoZXJuIGlociBhbmdlYm90IHJlbGF0aXYgYnJlaXQgdW5kIGhhYmVuIG5lYmVuIDExMC41NyBtaW8gaW4gUmFjaW5nIGF1Y2ggMTA0IG1pbyBpbiBQbGF0Zm9ybSwgODAgbWlvIGluIE1pc2MgdW5kIDk0LjUgbWlvIGluIEFjdGlvbi4gVGFrZS1Ud28gbWl0IEdyYW5kIFRoZWZ0IEF1dG8gdW5kIFJlYWQgZGVhZCBSZWRlbXB0aW9uIHNwZXppZmllcmVuIHNpY2ggd2VuaWcgdmVyd3VuZGVybGljaCBhdWYgQWN0aW9uIHdvaGluZ2VnZW4gc2ljaCBUSFEgd2llZGVyIHJlbGF0aXYgYnJlaXQgZsOkY2hlcnQuIFp1IGd1dGVyIGxldHp0IGbDpGhydCBVYmlzb2Z0IGVpbmUgendlaWdldGVpbHRlIFNjaG5pZW5lIG1pdCBBY3Rpb24gKEFzc2Fzc2luJ3MgQ3JlZWQpIHVuZCBNaXNjIChKdXN0IERhbmNlKS4NCg0KIyMjIEFuemFobA0KDQpgYGB7ciBwbG90KEFtb3VudEdlbnJlYnlQdWJsaXNoZXIpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQoNCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcixHZW5yZSkgJT4lIA0KICBzdW1tYXJpemUoQW56YWhsID1uKCksc3VtKEdsb2JhbF9TYWxlcykpICAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEdsb2JhbF9TYWxlcykiDQogICAgKQ0KDQpQdWJsaXNoZXJTYWxlcyA8LSBncm91cGVkICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkgJT4lIGZpbHRlcihHbG9iYWxfU2FsZXM+MzAwKQ0KDQoNCg0KZ3JvdXBlZCA8LSBncm91cGVkICAlPiUgZmlsdGVyKFB1Ymxpc2hlciAlaW4lIFB1Ymxpc2hlclNhbGVzJFB1Ymxpc2hlcikNCg0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCmdyb3VwZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwoZ3JvdXBlZCRQdWJsaXNoZXIsICJFbnRlcnRhaW5tZW50IikNCmdyb3VwZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwoZ3JvdXBlZCRQdWJsaXNoZXIsICJJbnRlcmFjdGl2ZSIpDQpncm91cGVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKGdyb3VwZWQkUHVibGlzaGVyLCAiU3R1ZGlvcyIpDQpncm91cGVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKGdyb3VwZWQkUHVibGlzaGVyLCAiR2FtZXMiKQ0KZ3JvdXBlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChncm91cGVkJFB1Ymxpc2hlciwgIkdhbWUiKQ0KDQoNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkFuemFobCINCg0KKQ0KDQpncm91cGVkJT4lDQogIHBsb3RfbHkoeD1+UHVibGlzaGVyLA0KICAgICAgICAgICB5PX5BbnphaGwsDQogICAgICAgICAgICB0eXBlPSdiYXInLA0KICAgICAgICAgICBjb2xvcj1+R2VucmUgLGNvbG9ycyA9IG15UGFsZXR0ZSkgICU+JSANCiAgbGF5b3V0KHRpdGxlPSJBbnphaGwgcHJvIEdlbnJlIHBybyBQdWJsaXNoZXIiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXksDQogICAgICAgICBiYXJtb2RlID0gJ3N0YWNrJw0KICAgICAgICAgKQ0KDQoNCg0KYGBgDQoNCkJldHJhY2h0ZW4gd2lyIGRpZSBBbnphaGwgZGVyIFNwaWVsZSB1bmQgc3RlbGwgZGllc2UgZGVuIFZlcmthdWZzemFobGVuIGdlZ2Vuw7xiZXIgZsOkbGx0IGhpZXIgdm9yYWxsZW0gYXVmLCBkYXNzIEZpcm1lbiBtaXQgRm9jdXMgaW4gZGVuIFZlcmthdWZzemFobGVuIGRpZXNlIGluIGRlciBQcm9kdWt0aW9uIG5vY2ggbWVociBQcmlvcml0aXNpZXJlbi4gSW50ZXJlc3NhbnQgaXN0IGF1Y2gsIGRhcyBBY3Rpdmlzb24gcHJvZHVrdGlvbnNmb2N1cyBkZXV0bGljaCBtZWhyIGF1ZiBhY3Rpb24gR2FtZXMgbGllZ3QgYWxzIGF1ZiBTaG9vdGVybiBkaWVzZSBzaWNoIGltIHZlcmdsZWljaCBqZWRvY2ggZGV1dGxpY2ggc2NobGVjaHRlciB2ZXJrYXVmZW4uDQoNCiMjIHstfQ0KDQpCZWkgZGVtIHZlcmdsZWljaCBkZXIgV2VydGUgaXN0IGhpZXIgenUgYmVtZXJrZW4sIGRhc3MgZGllIG1laXN0ZW4gUHVibGlzaGVyIEhpZXJiZWkgc2ljaCBtaXQgZGVyIEFuemFobCBkZXIgU3BpZWxlIHVuZCBkZW4gU2FsZXMgZ3V0IGFiZGVja2VuLiBEaWUgYXVmZsOkbGxpZ3N0ZW4gZGlza3JlcGFuemVuIHNpbmQgaGllcmJlaSBFQSBtaXQgZGVtIFNwb3J0cyBHZW5yZSB1bmQgaWhyZW4gasOkcmxpY2ggcmVsZWFzdGVuIFNwaWVsZW4gRmlGYS9OQkEyayBldGMuIHNvd2llIE5pbnRlbmRvIG1pdCBkZXIgUGxhdGZvcm1yZWloZSBTdXBlciBNYXJpby4gDQoNCioqKg0KDQoNCiMgR2VucmV2ZXJ0ZWlsdW5nIGbDvHIgUHVibGlzaGVyIEVsZWN0cm9uaWMgQXJ0c3sjR2VucmVCeVB1Ymxpc2hlckVBfSANCg0KU2NoYXVlbiB3aXIgdW5zIGRpZXNlIEJlaWRlbiBGaXJtZW4gbm9jaCBlaW5tYWwgaW0gRGV0YWlsIGFuLiBIaWVyenUgdmVyd2VuZGVuIHdpciBlcm5ldXQgW1BhcmV0by1dKCNQbGF0Zm9ybWFuYWx5c2UpIHVuZCBbS3JlaXNkaWFncmFtbV0oI1BsYXRmb3JtUmFua2luZ0J5UmVnaW9uKSBkaWUgdW5zIGJlcmVpdHMgYXVzIHZvcmRlcmVuIFRlaWxlbiBkZXIgQXVzYXJiZWl0dW5nIGJla2FubnQgc2luZC4NCg0KIyMgR2VucmUgZsO8ciBFbGVjdHJvbmljIEFydHMgey50YWJzZXR9DQoNCiMjIyBCYWxrZW5kaWFncmFtbWUgey50YWJzZXR9DQoNCiMjIyMgVmVya2F1ZnN6YWhsZW4gDQoNCmBgYHtyIHBsb3QoR2VucmVieVB1Ymxpc2hlckVBMSksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcixHZW5yZSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEdsb2JhbF9TYWxlcykiDQogICAgKSAlPiUgDQogIGZpbHRlcihQdWJsaXNoZXIgPT0gIkVsZWN0cm9uaWMgQXJ0cyIpDQoNCg0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlZlcmvDpHVmZSAoaW4gbWlvKSINCg0KKQ0KDQpncm91cGVkJT4lDQogIHBsb3RfbHkoKSAlPiUgYWRkX2JhcnMoeD1+R2VucmUsDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgY29sb3I9fkdlbnJlICxjb2xvcnMgPSBteVBhbGV0dGUpICAlPiUgDQogIGxheW91dCh0aXRsZT0iVmVya2F1ZnN6YWhsZW4gZsO8ciBFbGVjdHJvbmljIEFydHMiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXksDQogICAgICAgICBiYXJtb2RlID0gJ3N0YWNrJywNCiAgICAgICAgIHNob3dsZWdlbmQgPSBGQUxTRQ0KICAgICAgICAgKQ0KDQpgYGANCg0KQmVpbSBCZXRyYWNodGVuIGRlciBTYWxlcyBlcmtlbm5lbiB3aXIgZGFzIHdpZSBiZXJlaXRzIHZvcmhlciBmZXN0Z2VzdGVsbHQgU3BvcnRzICg0NzkuNjcgbWlvKSBhbiBlcnN0ZXIgU3RlbGxlIHN0ZWh0LiBNaXQgZGV1dGxpY2hlbSBBYnN0YW5kIGRhbmFjaCBmb2xnZW4gU2hvb3RlciAoMTU4LjI2IG1pbyksIFJhY2luZyAoMTQ1Ljc3IG1pbykgdW5kIEFjdGlvbiAoMTE1LjU0IG1pbykuIERhcyBlaW56aWcgYW5kZXJlIFJlbGV2YW50ZSBHZW5yZSBpc3QgU2ltdWxhdGlvbiBtaXQgODkuNTMgbWlvIGluIFNhbGVzLiBSb2xlLVBsYXlpbmcgKDM1LjMgbWlvKSwgRmlnaHRpbmcgKDMxLjM5IG1pbyksIE1pc2MgKDI0Ljk1IG1pbykgc293aWUgU3RyYXRlZ3kgKDE0LjA4IG1pbyksIFBsYXRmb3JtICg2LjUzIG1pbyksIEFkdmVudHVyZSAoNC43NSBtaW8pIHVuZCBQdXp6bGUgKDQuNTUgbWlvKSBzcGllbGVuIGVpbmUgZWhlciB1bnRlcmdlb3JkbmV0ZSBSb2xsZS4NCg0KIyMjIyBBbnphaGwNCg0KYGBge3IgcGxvdChBbW91bnRHZW5yZWJ5UHVibGlzaGVyRUExKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcixHZW5yZSkgJT4lIA0KICBzdW1tYXJpemUoQW56YWhsID1uKCkpICAlPiUgDQogIGZpbHRlcihQdWJsaXNoZXIgPT0gIkVsZWN0cm9uaWMgQXJ0cyIpDQoNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkFuemFobCINCg0KKQ0KDQoNCmdyb3VwZWQlPiUNCiAgcGxvdF9seSgpICU+JSBhZGRfYmFycyh4PX5HZW5yZSwNCiAgICAgICAgICAgeT1+QW56YWhsLA0KICAgICAgICAgICBjb2xvcj1+R2VucmUgLGNvbG9ycyA9IG15UGFsZXR0ZSkgICU+JSANCiAgbGF5b3V0KHRpdGxlPSJBbnphaGwgZGVyIFNwaWVsZXJlbGVhc2VzIG5hY2ggR2VucmUgZsO8ciBFbGVjdHJvbmljIEFydHMgIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5LA0KICAgICAgICAgYmFybW9kZSA9ICdzdGFjaycsDQogICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UNCiAgICAgICAgICkNCg0KYGBgDQoNCkluIGRlciBEZXRhaWxsYW5zaWNodCBzZWhlbiBBbnphaGwgZGVyIFNwaWVsZSB1bmQgU2FsZXMgZGV1dGxpY2ggZ2VyaW5nZXIgYXVzLiBEZW4gZXJzdGVuIFBsYXR6IGJlbGVndCB3ZWl0ZXJoaW4gU3BvcnRzICg1NjEpIHZvciBBY3Rpb24gKDE4MyksIFJhY2luZyAoMTU5KSwgU2hvb3RlciAoMTM5KSB1bmQgU2ltdWxhdGlvbiAoMTE2KS4gQXVjaCBkaWUgZWhlciBpcmVsZXZhbnRlbiBHZW5yZXMgd2llIE1pc2MgKDQ2KSwgRmlnaHRpbmcgKDM5KSB1bmQgU3RyYXRlZ3kgKDM3KSBzaW5kIHdlaXRlcmhpbiBrYXVtIHZlcnRyZXRlbi4NCg0KIyMjIEtyZWlzZGlhZ3JhbW1lIHsudGFic2V0fQ0KDQojIyMjIFZlcmthdWZzemFobGVuIA0KDQpgYGB7ciBwbG90KEdlbnJlYnlQdWJsaXNoZXJFQTIpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIsR2VucmUpICU+JSANCiAgc3VtbWFyaXplKHN1bShHbG9iYWxfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkgJT4lIA0KICBmaWx0ZXIoUHVibGlzaGVyID09ICJFbGVjdHJvbmljIEFydHMiKQ0KDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJWZXJrw6R1ZmUgKGluIG1pbykiDQoNCikNCg0KZ3JvdXBlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfcGllKHZhbHVlcyA9fkdsb2JhbF9TYWxlcyxsYWJlbHM9fkdlbnJlLHRleHRpbmZvPSdsYWJlbCtwZXJjZW50Jywgcm90YXRpb24gPSAxMTAsIHNvcnQgPSBGQUxTRSwNCiAgICAgICAgICAgbmFtZT0iVmVya2F1ZnN6YWhsZW4gcHJvIEdlbnJlIGbDvHIgRWxlY3Ryb25pYyBBcnRzIiAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iVmVya2F1ZnN6YWhsZW4gcHJvIEdlbnJlIGbDvHIgRWxlY3Ryb25pYyBBcnRzIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5LA0KICAgICAgICAgc2hvd2xlZ2VuZCA9IEZBTFNFLA0KICAgICAgICAgYXV0b3NpemUgPSBGDQogICAgICAgICApDQoNCg0KYGBgDQoNCkJlaW0gQmV0cmFjaHRlbiBkZXIgU2FsZXMgZXJrZW5uZW4gd2lyIGRhcyB3aWUgYmVyZWl0cyB2b3JoZXIgZmVzdGdlc3RlbGx0IFNwb3J0cyAoNDMuMiUpIGFuIGVyc3RlciBTdGVsbGUgc3RlaHQuIE1pdCBkZXV0bGljaGVtIEFic3RhbmQgZGFuYWNoIGZvbGdlbiBTaG9vdGVyICgxNC4zJSksIFJhY2luZyAoMTMuMSUpIHVuZCBBY3Rpb24gKDEwLjQlKS4gRGFzIGVpbnppZyBhbmRlcmUgUmVsZXZhbnRlIEdlbnJlIGlzdCBTaW11bGF0aW9uIG1pdCA4LjA2JSBkZXIgU2FsZXMuIFJvbGUtUGxheWluZyAoMy4xOCUpLCBGaWdodGluZyAoMi44MyUpLCBNaXNjICgyLjI1JSkgc293aWUgU3RyYXRlZ3kgKDEuMjclKSwgUGxhdGZvcm0gKDAuNTg4JSksIEFkdmVudHVyZSAoMC40MjglKSB1bmQgUHV6emxlICgwLjQxJSkgc3BpZWxlbiBlaW5lIGVoZXIgdW50ZXJnZW9yZG5ldGUgUm9sbGUuDQoNCiMjIyMgQW1uemFobA0KDQpgYGB7ciBwbG90KEFtb3VudEdlbnJlYnlQdWJsaXNoZXJFQTIpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyLEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShBbnphaGwgPW4oKSkgICU+JSANCiAgZmlsdGVyKFB1Ymxpc2hlciA9PSAiRWxlY3Ryb25pYyBBcnRzIikNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJHZW5yZSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiQW56YWhsIg0KDQopDQoNCmdyb3VwZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX3BpZSh2YWx1ZXMgPX5BbnphaGwsbGFiZWxzPX5HZW5yZSx0ZXh0aW5mbz0nbGFiZWwrcGVyY2VudCcsc29ydCA9IFRSVUUsIHJvdGF0aW9uID0gOTAsDQogICAgICAgICAgIG5hbWU9IkFuemFobCBkZXIgU3BpZWxlcmVsZWFzZXMgcHJvIEdlbnJlIGbDvHIgRWxlY3Ryb25pYyBBcnRzIiAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iQW56YWhsIGRlciBTcGllbGVyZWxlYXNlcyBwcm8gR2VucmUgZsO8ciBFbGVjdHJvbmljIEFydHMiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXksDQogICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UsDQogICAgICAgICBhdXRvc2l6ZSA9IEYNCiAgICAgICAgICkNCg0KYGBgDQoNCkluIGRlciBEZXRhaWxsYW5zaWNodCBzZWhlbiBBbnphaGwgZGVyIFNwaWVsZSB1bmQgU2FsZXMgZGV1dGxpY2ggZ2VyaW5nZXIgYXVzLiBEZW4gZXJzdGVuIFBsYXR6IGJlbGVndCB3ZWl0ZXJoaW4gU3BvcnRzICg0MS41JSkgdm9yIEFjdGlvbiAoMTMuNSUpLCBSYWNpbmcgKDExLjglKSwgU2hvb3RlciAoMTAuMyUpIHVuZCBTaW11bGF0aW9uICg4LjU5JSkuIEF1Y2ggZGllIGVoZXIgaXJlbGV2YW50ZW4gR2VucmVzIHdpZSBNaXNjICgzLjQlKSwgRmlnaHRpbmcgKDIuODklKSB1bmQgU3RyYXRlZ3kgKDIuNzQlKSBzaW5kIHdlaXRlcmhpbiBrYXVtIHZlcnRyZXRlbi4NCg0KIyMgey19DQoNClNjaGF1ZW4gd2lyIHVucyBFQSBoaWVyIGltIERldGFpbCBhbiBmw6RsbHQgYXVmIGRhcyBkaWUgRGlza3JlcGFueiB6d2lzY2hlbiBTYWxlcyB1bmQgQW56YWhsIGRlciBHYW1lcmVsZWFzZXMgZsO8ciBFQSBiZWkgU3BvcnRzIGdhciBuaWNodCBzbyBncm/DnyBpc3QgKDQxLjUlIHZzIDQzLjIlKSB3aWUgdm9yaGVyIGdlZGFjaHQuIERpZSBncsO2w59lcmVuIGRpc2tyZXBhbnplbiBzaW5kIGhpZXIgU2hvb3RlciB3ZWxjaGVzIG51ciAxMCUgZGVyIEdhbWVyZWxlYXNlcyBzaW5kIGFiZXIgZ3V0IDE1JSBkZXIgU2FsZXMgdW5kIEFjdGlvbiBtaXQgMTMuNSUgZGVyIEdhbWVyZWxlYXNlcyB1bmQgMTAuNCUgZGVyIFNhbGVzLg0KDQojIEdlbnJldmVydGVpbHVuZyBmw7xyIE5pbnRlbmRvIHsjR2VucmVCeVB1Ymxpc2hlck5pbnRlbmRvfSANCg0KTmFjaGRlbSB3aXIgbnVuIGhlcmF1c2dlZnVuZGVuIGhhYmVuIGRhcyBiZWkgRWxlY3Ryb25pYyBBcnRzIGRpZSBEaXNrcmVwYW56IHp3aXNjaGVuIFNhbGVzIHVuZCBBbnphaGwgZGVyIFNwaWVsZSBnYXIgbmljaHQgc28gZ3Jvw58gaXN0IHdpZSB2b3JoZXIgZ2VkYWNodCBiZXRyYWNodGVuIHdpciBudW4gZGllIGdsZWljaGVuIERhdGVuIGbDvHIgTmludGVuZG8uIERpZSBGcmFnZSBkaWUgc2ljaCBoaWVyIHN0ZWxsdCBpc3Qgb2IgYmVpIE5pbnRlbmRvIGVpbiDDpGhubGljaGVyIHZlcmxhdWYgZmVzdHN0ZWxsYmFyIGlzdCBvZGVyIG9iIHNpY2ggYmVpIGRpZXNlbiBiZXN0aW1tdGUgR2VucmVzIGVpbmZhY2ggZGV1dGxpY2ggYmVzc2VyIHZlcmthdWZlbiBhbHMgc2llIHNvbGx0ZW4uDQoNCioqKg0KDQojIyBHZW5yZXZlcnRlaWx1bmcgZsO8ciBOaW50ZW5kbyB7LnRhYnNldH0NCg0KIyMjIEJhbGtlbmRpYWdyYW1tZSB7LnRhYnNldH0NCg0KIyMjIyBWZXJrYXVmc3phaGxlbg0KDQpgYGB7ciBwbG90KEdlbnJlYnlQdWJsaXNoZXJOaW50ZW5kbzEpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIsR2VucmUpICU+JSANCiAgc3VtbWFyaXplKHN1bShHbG9iYWxfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkgJT4lIA0KICBmaWx0ZXIoUHVibGlzaGVyID09ICJOaW50ZW5kbyIpDQoNCg0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlZlcmvDpHVmZSAoaW4gbWlvKSINCg0KKQ0KDQpncm91cGVkJT4lDQogIHBsb3RfbHkoKSAlPiUgYWRkX2JhcnMoeD1+R2VucmUsDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgY29sb3I9fkdlbnJlICxjb2xvcnMgPSBteVBhbGV0dGUpICAlPiUgDQogIGxheW91dCh0aXRsZT0iVmVya2F1ZnN6YWhsZW4gcHJvIEdlbnJlIGbDvHIgTmludGVuZG8iLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXksDQogICAgICAgICBiYXJtb2RlID0gJ3N0YWNrJywNCiAgICAgICAgIHNob3dsZWdlbmQgPSBGQUxTRQ0KICAgICAgICAgKQ0KDQoNCmBgYA0KDQpXaWUgYmVyZWl0cyBpbiBkZXIgW0dlbnJlYW5hbHlzZSBkZXIgUHVibGlzaGVyXSgjR2VucmVCeVB1Ymxpc2hlckdsb2JhbCkgZmVzdGdlc3RlbGx0IHZlcmthdWZlbiBzaWNoIFBsYXRmb3JtLVNwaWVsZSAoNDI3LjIxIG1pbykgZsO8ciBOaW50ZW5kbyBhbSBiZXN0ZW4uIERvY2ggYXVjaCBSb2xlLVBsYXlpbmcgKDI4NC45IG1pbyksIFNwb3J0cyAoMjE4IG1pbykgdW5kIE1pc2MgKDE4MC42NyBtaW8pIG1hY2hlbiBrZWluZW4gdW53ZXNlbnRsaWNoZW4gVGVpbCBpaHJlciBWZXJrw6R1ZmUgYXVzLiBTZWxic3QgZGllIHdlbmlnZXIgUHJvbWluZW50ZW4gR2VucmVzIHdpZSBSYWNpbmcgKDE1MS4zIG1pbyksIEFjdGlvbiAoMTI4LjE4IG1pbykgdW5kIFB1enpsZSAoMTI0Ljg4IG1pbykuIHZlcmthdWZlbiBzaWNoIGltbWVybm9jaCBkZXV0bGljaCBiZXNzZXIgYWxzIGRpZSBlbnRzcHJlY2hlbmRlbiBTcGllbGVnZW5yZXMgZGVyIEtvbmt1cnJlbnogRUEuIEFtIGRldXRsaWNoc3RlbiBpc3QgZGVyIFVudGVyc2NoaWVkIHZlcm11dGxpY2ggYmVpIGRlbiBnYW56ICJrbGVpbmVuIiBHZW5yZXMgU2ltdWxhdGlvbiAoODUuMjcgbWlvKSwgU2hvb3RlciAoNjkuNzMgbWlvKSwgRmlnaHRpbmcgKDUzLjM1IG1pbykgdW5kIEFkdmVudHVyZSAoMzUuNzEpLiBBdWNoIHdlbm4gZGllc2Ugc2ljaCBuaWNodCBhbiBkZXIgRXhha3QgZ2xlaWNoZW4gc3RlbGxlIGluIGRlciBSYW5nbGlzdGUgZGVyIFNhbGVzIGJlZmluZGVuIGhhdCBkZXIgbGV0enRlIFBsYXR6IHZvbiBOaW50ZW5kbyBTdHJhdGVneSAoMjcuMzUlKSBkZW5ub2NoIG1laHIgYWxzIGRhcyA2IEZhY2hlIGFuIFNhbGVzIGFscyBkZXIgdm9uIEVBLiBUcm90eiBkYXMgTmludGVuZG8gbWVociBUb3RhbCBTYWxlcyBoYXQgYWxzIEVsZWN0cm9uaWMgQXJ0cyBpc3QgZGllc2VyIHdlcnQgbmljaHQgNiBtYWwgc28gZ3Jvw58gc29uZGVybiB1bWZhc3N0IG5pY2h0bWFsIGRhcyBkb3BwZWx0ZS4NCg0KIyMjIyBBbnphaGwNCmBgYHtyIHBsb3QoQW1vdW50R2VucmVieVB1Ymxpc2hlck5pbnRlbmRvMSksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIsR2VucmUpICU+JSANCiAgc3VtbWFyaXplKEFuemFobCA9bigpKSAgJT4lIA0KICBmaWx0ZXIoUHVibGlzaGVyID09ICJOaW50ZW5kbyIpDQoNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJHZW5yZSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiQW56YWhsIg0KDQopDQoNCg0KDQpncm91cGVkJT4lDQogIHBsb3RfbHkoKSAlPiUgYWRkX2JhcnMoeD1+R2VucmUsDQogICAgICAgICAgIHk9fkFuemFobCwNCiAgICAgICAgICAgY29sb3I9fkdlbnJlICxjb2xvcnMgPSBteVBhbGV0dGUpICAlPiUgDQogIGxheW91dCh0aXRsZT0iQW56YWhsIGRlciBTcGllbGVyZWxlYXNlcyBuYWNoIEdlbnJlIGbDvHIgTmludGVuZG8iLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXksDQogICAgICAgICBiYXJtb2RlID0gJ3N0YWNrJywNCiAgICAgICAgIHNob3dsZWdlbmQgPSBGQUxTRQ0KICAgICAgICAgKQ0KDQpgYGANCg0KSW0gZXJzdGVuIE1vbWVudCBmw6RsbHQgZGlyZWt0IGF1ZiwgZGFzcyBkZXIgQXVzc2NobGFnIHZvbiBQbGF0Zm9ybSAoMTEyKSBoaWVyIGRldXRsaWNoIGdlcmluZ2VyIGF1c2bDpGxsdCBhbHMgbm9jaCBpbiBkZW4gVmVya2F1ZnN6YWhsZW4uIFNvd29obCBSb2xlLVBsYXlpbmcgKDEwNikgYWxzIGF1Y2ggTWlzYyAoMTAwKSB1bWZhc3NlbiBudXIgZWluIHBhYXIgd2VuaWdlciBTcGllbGUuIEF1Y2ggZGFzIE1pdHRlbGZlbGQgdW1mYXNzdCBtaXQgQWN0aW9uICg3OSksIFB1enpsZSAoNzQpIHVuZCBTcG9ydHMgKDU1KSBpbW1lcm5vY2ggZWluZSBSZWxhdGl2IGdyb8OfZSBBbnphaGwgYW4gU3BpZWxlbi4gU2VsYnN0IGRpZSBoaW50ZXJlbiBQbMOkdHplIG1pdCBSYWNpbmcgKDM3KSwgQWR2ZW50dXJlICgzNSkgdW5kIFN0cmF0ZWd5ICgzMikgc2luZCBudXIga25hcHAgdm9yIFNpbXVsYXRpb24gKDI5KSwgU2hvb3RlciAoMjYpIHVuZCBGaWdodGluZyAoMTgpLg0KDQojIyMgS3JlaXNkaWFncmFtbWUgey50YWJzZXR9DQoNCiMjIyMgVmVya2F1ZnN6YWhsZW4NCg0KYGBge3IgcGxvdChHZW5yZWJ5UHVibGlzaGVyTmludGVuZG8yKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyLEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSANCiAgZmlsdGVyKFB1Ymxpc2hlciA9PSAiTmludGVuZG8iKQ0KDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJWZXJrw6R1ZmUgKGluIG1pbykiDQoNCikNCg0KZ3JvdXBlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfcGllKHZhbHVlcyA9fkdsb2JhbF9TYWxlcyxsYWJlbHM9fkdlbnJlLHRleHRpbmZvPSdsYWJlbCtwZXJjZW50Jyxzb3J0ID0gVFJVRSwNCiAgICAgICAgICAgbmFtZT0iVmVya8OkdWZlIG5hY2ggR2VucmUgZsO8ciBOaW50ZW5kbyIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlZlcmvDpHVmZSBuYWNoIEdlbnJlIGbDvHIgTmludGVuZG8iLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXksDQogICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UsDQogICAgICAgICBhdXRvc2l6ZSA9IEYNCiAgICAgICAgICkNCg0KDQpgYGANCg0KV2llIGJlcmVpdHMgaW4gZGVyIFtHZW5yZWFuYWx5c2UgZGVyIFB1Ymxpc2hlcl0oI0dlbnJlQnlQdWJsaXNoZXJHbG9iYWwpIGZlc3RnZXN0ZWxsdCB2ZXJrYXVmZW4gc2ljaCBQbGF0Zm9ybS1TcGllbGUgKDIzLjklKSBmw7xyIE5pbnRlbmRvIGFtIGJlc3Rlbi4gRG9jaCBhdWNoIFJvbGUtUGxheWluZyAoMTUuOSUpLCBTcG9ydHMgKDEyLjIlKSB1bmQgTWlzYyAoMTAuMSUpIG1hY2hlbiBrZWluZW4gdW53ZXNlbnRsaWNoZW4gVGVpbCBpaHJlciBWZXJrw6R1ZmUgYXVzLiBTZWxic3QgZGllIHdlbmlnZXIgUHJvbWluZW50ZW4gR2VucmVzIHdpZSBSYWNpbmcgKDguNDclKSwgQWN0aW9uICg3LjE3JSkgdW5kIFB1enpsZSAoNi45OSUpLiB2ZXJrYXVmZW4gc2ljaCBpbW1lcm5vY2ggZGV1dGxpY2ggYmVzc2VyIGFscyBkaWUgZW50c3ByZWNoZW5kZW4gU3BpZWxlZ2VucmVzIGRlciBLb25rdXJyZW56IEVBLiBBbSBkZXV0bGljaHN0ZW4gaXN0IGRlciBVbnRlcnNjaGllZCB2ZXJtdXRsaWNoIGJlaSBkZW4gZ2FueiAia2xlaW5lbiIgR2VucmVzIFNpbXVsYXRpb24gKDQuNzclKSwgU2hvb3RlciAoMy45JSksIEZpZ2h0aW5nICgyLjk5JSkgdW5kIEFkdmVudHVyZSAoMiUpLiBBdWNoIHdlbm4gZGllc2Ugc2ljaCBuaWNodCBhbiBkZXIgRXhha3QgZ2xlaWNoZW4gc3RlbGxlIGluIGRlciBSYW5nbGlzdGUgZGVyIFNhbGVzIGJlZmluZGVuIGhhdCBkZXIgbGV0enRlIFBsYXR6IHZvbiBOaW50ZW5kbyBTdHJhdGVneSAoMS41MyUpIGRlbm5vY2ggbWVociBhbHMgZGFzIDYgRmFjaGUgYW4gU2FsZXMgYWxzIGRlciB2b24gRUEuIFRyb3R6IGRhcyBOaW50ZW5kbyBtZWhyIFRvdGFsIFNhbGVzIGhhdCBhbHMgRWxlY3Ryb25pYyBBcnRzIGlzdCBkaWVzZXIgd2VydCBuaWNodCA2IG1hbCBzbyBncm/DnyBzb25kZXJuIHVtZmFzc3QgbmljaHRtYWwgZGFzIGRvcHBlbHRlLg0KDQojIyMjIEFuemFobA0KDQpgYGB7ciBwbG90KEFtb3VudEdlbnJlYnlQdWJsaXNoZXJOaW50ZW5kbzIpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyLEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShBbnphaGwgPW4oKSkgICU+JSANCiAgZmlsdGVyKFB1Ymxpc2hlciA9PSAiTmludGVuZG8iKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJBbnphaGwiDQoNCikNCg0KZ3JvdXBlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfcGllKHZhbHVlcyA9fkFuemFobCxsYWJlbHM9fkdlbnJlLHRleHRpbmZvPSdsYWJlbCtwZXJjZW50Jyxzb3J0ID0gVFJVRSwNCiAgICAgICAgICAgbmFtZT0iQW56YWhsIG5hY2ggR2VucmUgZsO8ciBOaW50ZW5kbyIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IkFuemFobCBuYWNoIEdlbnJlIGbDvHIgTmludGVuZG8iLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXksDQogICAgICAgICBzaG93bGVnZW5kID0gRkFMU0UNCiAgICAgICAgICkNCg0KYGBgDQoNCkltIGVyc3RlbiBNb21lbnQgZsOkbGx0IGRpcmVrdCBhdWYsIGRhc3MgZGVyIEF1c3NjaGxhZyB2b24gUGxhdGZvcm0gKDE1LjklKSBoaWVyIGRldXRsaWNoIGdlcmluZ2VyIGF1c2bDpGxsdCBhbHMgbm9jaCBpbiBkZW4gVmVya2F1ZnN6YWhsZW4uIFNvd29obCBSb2xlLVBsYXlpbmcgKDE1LjElKSBhbHMgYXVjaCBNaXNjICgxNC4xJSkgdW1mYXNzZW4gbnVyIGVpbiBwYWFyIHdlbmlnZXIgU3BpZWxlLiBBdWNoIGRhcyBNaXR0ZWxmZWxkIHVtZmFzc3QgbWl0IEFjdGlvbiAoMTEuMiUpLCBQdXp6bGUgKDEwLjUlKSB1bmQgU3BvcnRzICg3LjgyJSkgaW1tZXJub2NoIGVpbmUgUmVsYXRpdiBncm/Dn2UgQW56YWhsIGFuIFNwaWVsZW4uIFNlbGJzdCBkaWUgaGludGVyZW4gUGzDpHR6ZSBtaXQgUmFjaW5nICg1LjI2JSksIEFkdmVudHVyZSAoNC45OCUpIHVuZCBTdHJhdGVneSAoNC41NSUpIHNpbmQgbnVyIGtuYXBwIHZvciBTaW11bGF0aW9uICg0LjEzJSksIFNob290ZXIgKDMuNyUpIHVuZCBGaWdodGluZyAoMi41NiUpLg0KDQoNCiMjIHstfQ0KDQpCZWltIHZlcmdsZWljaGVuIGRlciBXZXJ0ZSB2b24gTmludGVuZG8gd2lyZCBlaW5lbSBhdWZtZXJrc2FtZW4gYmVvYmFjaHRlciB6aWVtbGljaCBzY2huZWxsIGtsYXIsIGRhc3MgUGxhdGZvcm0gU3BpZWxlIGVpbiBLYXNzZW5jaGxhZ2VyIHNpbmQuIE5laG1lbiBkaWVzZSBudXIgMTYlIGRlciBzcGllbGVyZWxlYXNlcyBlaW4gc28gYnJpbmdlbiBzaWUgZGVubm9jaCAyNCUgZGVyIFNhbGVzIGVpbi4gR2xlaWNoZXMgR2lsdCBmw7xyIFNwb3J0IGdhbWVzLiA4JSBnZWdlbsO8YmVyIDEyJS4gQWN0aW9uICgxMSUgdnMgNyUpLCBNaXNjICgxNCUgdnMgMTAlKSB1bmQgUHV6emxlIEdhbWVzICgxMC41JSB2cyA3JSkgc2luZCBqZWRvY2ggbmljaHQgc28gZXJmb2xncmVpY2guIERpZSBGcmFnZSB3b3JhbiBkaWVzIGxpZWdlbiBrw7ZubnRlIHfDpHJlIGJlc3RpbW10IGF1Y2ggZWluZSBpbnRlcmVzc2FudGUgdW5kIGV0d2FzIGbDvHIgZWluZW4gW0F1c2JsaWNrIGluIGRpZSBadWt1bmZ0XSgjQXVzYmxpY2tJbkRpZVp1a3VuZnQpDQoNCioqKg0KDQoNCiMgQXVzYmxpY2sgaW4gZGllIFp1a3VuZnQgeyNBdXNibGlja0luRGllWnVrdW5mdH0NCg0KQmVpIGRlciBBbmFseXNlIGRlcyBEYXRlbnNhdHplcyBiZXppZWh1bmdzd2Vpc2UgZGVyIEVudHN0YW5kZW5lbiBHcmFmaWtlbiBzaW5kIHNvd29obCBkZW0gQXVmbWVya3NhbWVuIGxlc2VyIGFscyBhdWNoIG1pciBkZW0gRXJzdGVsbGVyIGVpbmlnZSB3ZWl0ZXIgSWRlZW4gYmV6aWVodW5nc3dlaXNlIHdlaXRlcmUgQW5zw6R0emUgZ2Vrb21tZW4gZGllIG1pdCBzaWNoZXJoZWl0IGludGVyZXNzYW50IHfDpHJlbiB6dSBWZXJmb2xnZS4gRWluaWdlIGRpZXNlciBCZWlzcGllbGUgaGFiZSBpY2ggaW0gRm9sZ2VuZGVuIGFscyBJZGVlbiBmw7xyIFp1a8O8bmZ0aWdlIFByb2pla3RlIE5pZWRlcmdlc2NocmllYmVuLiANCg0KKiBCZWltIFZlcmdsZWljaCBkZXIgYWxsZ2VtZWluZW4gW0dhbWUgU2FsZXNdKCNWaWRlb0dhbWVSZWxlYXNlcykgaGFiZW4gd2lyIGF1c3NjaGzDpGdlIEZlc3RnZXN0ZWxsdCBkaWUgbcO2Z2xpY2hlcndlaXNlIGV0d2FzIG1pdCBiZXN0aW1tdGVuIFZpZGVvc3BpZWxlbiBvZGVyIGFuZGVyZSDDpHXDn2VyZW4gRWluZmx1c3NmYWt0b3JlbiB3aWUgZGVuIGVpbmZhY2hlcmVuIFp1Z3JpZmYgYXVmIEtvbnNvbGVuLCBlaW5lIGJyZWl0ZXJlIEFremVwdGFueiBmw7xyIFZpZGVvc3BpZWxlIG9kZXIgZGllIEVudHdpY2tsdW5nIGRlcyBJbnRlcm5ldHMuIEVpbmUgZ2VuYXVlcmUgQW5hbHlzZSBkZXIgQXVzc2NobMOkZ2Ugd8OkcmUgZGVtZW50c3ByZWNoZW5kIGVpbiBJbnRlcmVzc2FudGVzIFRoZW1hLg0KDQoqIEludGVyZXNzYW50IHfDpHJlIERlbXRuc3ByZWNoZW5kIGF1Y2ggZWluZSBnZW5hdWVyZSBBbmFseXNlIGRlciBHYW1lc2FsZXMgcHJvIEphaHIgYWxzbyBpbiB3ZWxjaGVtIEphaHIgd2VsY2hlcyBTcGllbCB3aWUgb2Z0IGdla2F1ZnQgd3VyZGUuIFd1cmRlIEJlaXNwaWVsc3dlaXNlIFRldHJpcyAxOTUwIDMwIG1hbCB1bmQgMjAxNSAzMDAuMDAwIG1hbCB2ZXJrYXVmdC4gRGllcyBnZWJlbiBkaWUgdm9ybGllZ2VuZGVuIERhdGVuIGplZG9jaCBsZWlkZXIgbmljaHQgaGVyIGFsc28gd8OkcmUgZWluIGFuZGVyZSBEYXRlbnNhdHogYnp3IHdlaXRlcmUgRGF0ZW4gbm90d2VuZGlnLg0KDQoqIEltIGdsZWljaGVuIEdlZGFua2Vuc2Nocml0dCBrb21tdCBlaW5lIGFuYWx5c2UgZGVyIFZlcsOkbmRlcnVuZ2VuIGltIEthdWZ2ZXJoYWx0ZW4gd8OkaHJlbmQgZGVyIENyb25hcGFuZGVtaWUgdW5kIGRlbSBkYXJhdWYgZm9sZ2VuZGVuIExvY2tkb3duIGlzdCBhYmVyIGF1cyBnbGVpY2hlbSBHcnVuZCBsZWlkZXIgbmljaHQgbcO2Z2xpY2guDQoNCiogRGFzIEdsZWljaGUgVHJpZmZ0IGF1ZiBkaWUgW1ZlcmthdWZzemhsZW50d2lja2x1bmcgaW0gbGF1ZmUgZGVyIEphaHJlXSgjU2FsZXNQZXJQbGF0Zm9ybSkgbWl0IGVpbmVyIGdlbmF1ZXJuIEFuYWx5c2UgZGVyIHZlcmthdWZ0ZW4gU3BpZWxlIHBybyBQbGF0Zm9ybSBpbSBsYXVmZSBkZXIgSmFocmUgenUuDQoNCiogRGVzd2VpdGVyZW4gaGFiZW4gd2lyIHVucyBiZWltIHZlcmdsZWljaCAgZGVyIFtQbGF0Zm9ybWVuXSgjUGxhdGZvcm1hbmFseXNlKSBkaWUgRnJhZ2UgZ2VzdGVsbHQgd2llIHNpY2ggZGllIFNwaWVsZXZlcmvDpHVmZSBwcm8gUGxhdGZvcm0gdmVyaGFsdGVuLiBFaW4gVmVyZ2xlaWNoIGViZW5qZW5lciBEYXRlbiB3w6RocmUgZGVtZW50c3ByZWNoZW5kIGludGVyZXNzYW50IHVtIHp1IGtsw6RyZW4gb2Igc2ljaCBCaWVzcGllbHN3ZWlzZSBOaW50ZW5kb3NwaWVsZSBiZXNzZXIgYXVmIE5pbnRlbmRvIGtvbnNvbGVuIG9kZXIgU29ueSBTcGllbGUgYmVzc2VyIGF1ZiBkZXIgUGxheXN0YXRpb24gdmVya2F1ZmVuLiBEaWVzIGJlbsO2dGlndCBqZWRvY2ggdm9yYWxsZW0gYXVmZ3J1bmQgdm9uIEV4a2x1c2l2dGl0ZWxuIHdpZSAiVGhlIExlZ2VuZCBvZiBaZWxkYTogQnJlYXRoIG9mIHRoZSBXaWxkIiBvZGVyICJHb2Qgb2YgV2FyIiBleHRlbnNpdmUgYW5hbHlzZWFyYmVpdC4NCg0KKiBJbiBkZXIgW1B1Ymxpc2hlcmFuYWx5c2VdKCNQdWJsaXNoZXJSZWxlYXNlcykgaGFiZW4gd2lyIHVucyBBbnphaGwgZGVyIFNwaWVsZXJlbGVhc2VzIHNvd2llIEFuemFobCBkZXIgVmVya8OkdWZlIHZlcmdsaWNoZW4uIEludGVycmVhbnQgd8OkaHJlIGhpZXIgZWluIGRpcmVrdGVyIDEgenUgMSB2ZXJnbGVpY2ggbcO2Z2xpY2hlcndlaXNlIHNvZ2FyIHVudGVyIGJlenVnbmFobWUgYXVmIFBsYXRmb3JtZW4gdW5kIEdlbnJlcy4NCg0KKiBFaW4gdmVyZ2xlaWNoIGRlciBTcGllbGUgbmFjaCBIZXJzdGVsbGVycmVnaW9uIGluIGRlciBbUGxhdGZvcm1hbmFseXNdKCNQbGF0Zm9ybWFuYWx5c2UpIHfDpHJlIHNlaHIgaW50ZXJlc3NhbnQgZ2V3ZXNlbiBpc3QgamVkb2NoIGFuaGFuZCBkZXMgRGF0ZW5zYXR6ZXMgbGVpZGVyIG5pY2h0IG3DtmdsaWNoLiBTZWxic3QgZWluZSBhbm5haG1lIGRlcyBIZXJrdW5mdHNsYW5kZXMgYW5oYW5kIGRlcyBQdWJsaXNoZXJzIGlzdCBuaWNodCBtw7ZnbGljaCBkYSB2aWVsZSBQdWJsaXNoZXIgU3R1ZGlvcyBpbiB1bnRlcnNjaGllZGxpY2hzdGVuIEzDpG5kZXJuIHVuZCBSZWdpb25lbiBiZXRyZWlidC4gVWJpc29mdCBoYXQgYmVpc3BpZWxzd2Vpc2UgU3RhbmRvcnRlIGluIFBhcmlzLCBNYWlueiwgTmV3IFlvcmsgdW5kIFNpbmdhcHVyLg0KDQoqIEVpbiBSZWdpb25hbGVyIHZlcmdsZWljaCBhbmhhbmQgZGVyIEVpbndvaG5lcnphaGxlbiBlaW5lciBSZWdpb24gYnp3IGFsbGdlbWVpbiBlaW4gVmVyZ2xlaWNoIGRlciBTcGllbGV2ZXJrw6R1ZmUgbWl0IGRlciBFbnR3aWNrbHVuZyBkZXIgV2VsdGJldsO2bGtlcnVuZywgd2VsY2hlIHNpY2ggc2VpdCAxOTgwIFtmYXN0IHZlcmRvcHBlbHQgaGF0XShodHRwczovL2RlLnN0YXRpc3RhLmNvbS9zdGF0aXN0aWsvZGF0ZW4vc3R1ZGllLzE2OTQvdW1mcmFnZS9lbnR3aWNrbHVuZy1kZXItd2VsdGJldm9lbGtlcnVuZ3N6YWhsLykuDQoNCkRpZXMgaXN0IG51ciBlaW4ga2xlaW5lciBhdXNzY2huaXR0IGRlciBzY2hpZXIgdW5lbmRsaWNoZW4gTcO2Z2xpY2hrZWl0ZW4gZGllIGVpbmVtIGJlaSBkZXIgQW5hbHlzZSB2b24gZGVuIG1pdHRsZXJ3ZWlsZSBtZWhyIGFscyA0IG1pbyBWaWRlb3NwaWVsZW4gYmxlaWJ0IHVuZCBkYXMgbnVyIGFuZ2Vub21tZW4gd2lyIGJsZWliZW4gYmVpIGVpbmVtIGVoZXIgYWxsZ2VtZWluZXJlbSBWZXJnbGVpY2guIEplZGVzIGRpZXNlciBWaWRlb3NwaWVsZSBoYXQgdmVybXV0bGljaCBnZW51ZyDDtmZmZW50bGljaGUgRGF0ZW4gdW0gZWluZSBBcmJlaXQgenUgcHJvZHV6aWVyZW4gZGllIGVpbiB2aWVsZmFjaGVzIGRlcyBWb2x1bWVucyBkaWVzZXIgQXJiZWl0LCBmw7xyIHdlbGNoZSBtaXIgbnVyIGtuYXBwIDcwaCB6dSBWZXJmw7xndW5nIHN0YW5kZW4sIGhhdC4NCg0KIyBBdWZnZXRyZXRlbmUgUHJvYmxlbWUgeyNBdWZnZXRyZXRlbmVQcm9ibGVtZX0NCg0KTnVuIGFiZXIgenUgZGVtIHVuc2Now7ZuZW4gdGVpbCBlaW5lciBqZWRlciBBcmJlaXQuIERlbiBhdWZnZXRyZXRlbmVuIFByb2JsZW1lbiwgd2VsY2hlIGVudHdlZGVyIG5pY2h0IGzDtnNiYXIgb2RlciBlaW5lIHJlbGF0aXYgc3RhcmtlIMO8YmVyYXJiZWl0dW5nIGRlciBBdXNhcmJlaXR1bmcgbmFjaHppZWhlbiB3w7xyZGVuLg0KDQoqIERhcyBFcnN0ZSB1bmQgZsO8ciBkZW4gQXVmbWVya3NhbWVuIExlc2VyLCB3ZWxjaGVyIHNpY2ggdm9yYWxsZW0gZGllIExpbmUgUGxvdHMgaW0gZGlyZWt0ZW4gdmVyZ2xlaWNoIGFuZ2VzY2hhdXQgaGF0LCBvZmZlbnNpY2h0bGljaGUuIERlciBhbSBBbmZhZyBlcnN0ZWxsdGUgQ29sb3JicmV3ZXIsIHdlbGNoZXIgZGllIEZhcmJlbiBmw7xyIGRpZSBHcmFmaWtlbiBsaWVmZXJ0IHdpcmQgYXVzIGlyZ2VuZGVpbmFtIEdydW5kIG5pY2h0IGluIGplZGVyIEdyYWZpayBha3plcHRpZXJ0LiBEaWVzIHNjaGVpbnQgaGllciByZWluIHp1ZsOkbGxpZyB6dSBzZWluIHVuZCBmb2xndCBrZWluZW0gb2ZmZW5zaWNodGxpY2hlbSBQYXR0ZXJuLiBEZXIgRWluemlnZXIgdW50ZXJzY2hpZWQgendpc2NoZW4gRmlsbGVkIExpbmVzIHVuZCBTdGFja2VkIExpbmVzIGlzdCBkaWUgQWJ3ZXNlbmhlaXQgZGVzICpmaWxsKiBwYXJhbWV0ZXJzIHVuZCBzdGF0dGRlc3NlbiBkaWUgdmVyd2VuZHVuZyB2b24gKnN0YWNrZ3JvdXA9J29uZScqLiBUcm90eiBkaWVzZW4gbWluaW1hbGVuIHVudGVyc2NoaWVkZXMgQWt6ZXB0aWVydCBkaWUgRmlsbGVkIExpbmVzIEdyYWZpayBkaWUgRmFyYmF1c3dhaGwsIFN0YWNrZWQgTGluZXMgamVkb2NoIG5pY2h0Lg0KDQoqIEVpbiB3ZWl0ZXJlciBtaXIgdW5lcmtsw6RybGljaGVyIEZlaGxlciBpbiBkZXIgRG9rdW1lbnRlcnN0ZWxsdW5nIGlzdCBkaWUgw6RuZGVydW5nIGRlcyBGb3JtYXRzIG5hY2ggZGVtIGltcG9ydGllcmVuIGRlciBMaWJyYXJ5cy4gRXMgZ2lidCBrZWluZW4gb2ZmZW5zaWNodGxpY2hlbiBHcnVuZCB3YXJ1bSBzaWNoIGhpZXIgZGFzIEZvcm1hdCDDpG5kZXJuIHNvbGx0ZSBhdWYgZWlubWFsIGbDvGxsdCBkZXIgVGV4dCBqZWRvY2ggMTAwJSBkZXMgQmlsZHNjaGlybXMgd2FzIHouVC4genUgc2VociBzY2h3ZXIgenUgbGVzZW5lZGVuIFdvcnRlbiBmw7xocnQuDQoNCiogV2llIGJlcmVpdHMgaW4gZGVyIEFuYWx5c2UgZGVyIFtTYWxlcyBwZXIgR2FtZSBwZXIgWWVhcl0oI0dlbnJlU2FsZXNQZXJHYW1lUGVyWWVhcikgZmVzdGdlc3RlbGx0IHdlcmRlbiBTcGllbGUgaMOkdWZpZyBhdWYgbWVocmVyZW4gS29uc29sZW4gdmVyw7ZmZmVudGxpY2h0LiBFaW5lIHp1c2FtbWVuZmFzc3VuZyBkZXIgU3BpZWxlIHp1bSBad2VjayBkZXIgW1NhbGVzIHBlciBHYW1lXSgjVmlkZW9HYW1lUmVsZWFzZXMpIEFuYWx5c2Ugd8OkcmUgZGFmw7xyIHZvbm7DtnRlbi4NCg0KKiBCZWkgQmV0cmFjaHR1bmcgZGVzIENvZGVzLCB3ZWxjaGVyIGRpZSBHcmFmaWtlbiBlcnpldWd0IHdpcmQgZGVuIG1laXN0ZW4gYXVmZmFsbGVuLCBkYXNzIG9mdCBkb3BwZWx0ZXIgQ29kZSBkdXJjaCB2ZXJ3ZW5kdW5nIGluIG1laHJlcmVuIERpYWdyYW1tZW4gbWl0IG51ciBsZWljaHRlbiDDhG5kZXJ1bmdlbiBlbnRzdGVodC4gWnVzYW1tZW5mYXNzdW5nIGlzdCBoaWVyIGR1cmNoIGRpZSBOdXR6dW5nIHZvbiBtZWhyZXJlbiBEYXRhIEZyYW1lcyB1bmQgYW53ZW5kdW5nIGRlciBqZXdlaWxpZ2VuIGR1cmNoYXVzIG3DtmdsaWNoIGJlbsO2dGlndCBqZWRvY2ggenVtIFRlaWwgZ3JhdmllcmVuZGUgw7xiZXJhcmJlaXR1bmcgZGVyIGVpbnplbG5lbiBBYnNjaG5pdHRlLg0KDQoNCiogRWluIEZpbHRlcm4gZGVyIFtQbGF0Zm9ybXZlcmvDpHVmZSBwcm8gSmFocl0oI1NhbGVzUGVyUGxhdGZvcm0pIG5hY2ggdG90YWwgU2FsZXMgd8OkcmUgZGV1dGxpY2ggYmVzc2VyIGFscyBlaW4gRmlsdGVybiBuYWNoIGRlbiBTYWxlcyBpbiBlaW5lbSBKYWhyLiBEaWVzIHfDvHJkZSBkaWUgRXJ6ZXVndW5nIGVpbmVzIHp1c8OkdHpsaWNoZW4gRGF0YSBGcmFtZXMgYmVuw7Z0aWdlbiB3w6RyZSBqZWRvY2ggZGV1dGxpY2ggaW5mb3JtYXRpdmVyIGFscyBkZXIgYWt0dWVsbGUgc3RhbmQgYmVpIGRlbSBlaW5pZ2UgSmFocmUgZ2FueiBhdXMgZGVtIFNoZW1hIGZhbGxlbi4NCg0KKiBEYXMgW1B1Ymxpc2NoZXIgUmFua2luZyBuYWNoIFJlZ2lvbl0oI1B1Ymxpc2hlclJhbmtpbmdieVJlZ2lvbikgd8O8cmRlIHZlcm11dGxpY2ggdm9yYWxsZW0gZGllIGtsZWluZXJlIFJlZ2lvbiBKYXBhbiBlaW5lbiBkZXV0bGljaCBhbmRlcmVuIGF1c2dhbmcgYXVmemVpZ2VuLCBzb2xsdGUgbmljaHQgbmFjaCBkZXIgQW56YWhsIGRlciBTcGllbGUgc29uZGVybiBiZWlzcGllbHN3ZWlzZSBkZW0gd2VydCBkZXIgVmVya2F1ZnN6YWhsZW4gZ2VmaWx0ZXJ0IHdlcmRlLiBEaWVzIGbDvGhydCBqZWRvY2ggZGF6dSwgZGFzcyB1bnRlcnNjaGllZGxpY2hlbiBQdWJsaXNoZXIgdmVyZ2xpY2hlbiB3ZXJkZW4gd2FzIGRlbiBpbmZvcm1hdGlvbnNnZWhhbHQgbWluaW1pZXJlbiB3w7xyZGUuDQoNCiogQmVpIGRlciBbUGxhdGZvcm1hbmFseXNdKCNQbGF0Zm9ybWFuYWx5c2UpIHdpcmQgZGVuIG1laXN0ZW4sIHZvcmFsbGVtIG5pY2h0IEdhbWluZ3ZlcnNpZXJ0ZW4gTGVzZXJuIGF1ZmdlZmFsbGVuIHNlaW4gZGFzIE1vYmlsZWdhbWVzIGltIERhdGVuc2F0eiBrb21wbGV0dCBmZWhsZW4uIEFscyBkaWUgd29obCBhbSB3ZWl0IHZlcnRyZXRlbnN0ZSB1bmQgbWl0dGxlcndlaWxlIFt1bXNhdHpzdMOkcmtzdGVdKGh0dHBzOi8vZGUuc3RhdGlzdGEuY29tL2luZm9ncmFmaWsvMjI0MTQvdW1zYXR6LWF1c2dld2FlaGx0ZXItc2VrdG9yZW4tZGVyLXVudGVyaGFsdHVuZ3NpbmR1c3RyaWUvKSBQbGF0Zm9ybSBiZWVpbmZsdXNzdCBkaWVzIGRlbiBEYXRlbnNhdHogdW5nZW1laW4uIEFsbGdlbWVpbiBzaW5kIG51ciBrbmFwcCAxNi4wMDAgZGVyIHdlbHR3ZWl0IG1laHIgYWxzIFszLjMgbWlvXSggaHR0cHM6Ly93d3cuc3RhdGlzdGEuY29tL3N0YXRpc3RpY3MvMjkzMzA0L251bWJlci12aWRlby1nYW1lcnMvIzp+OnRleHQ9SW4lMjB0b3RhbCUyQyUyMHRoZXJlJTIwd2VyZSUyMGFuLGJpbGxpb24lMjBnYW1lcnMlMjBhY3Jvc3MlMjB0aGUlMjBnbG9iZSkgVmlkZW9zcGllbGUgaW4gZGVtIERhdGVuc2F0eiB2b3JoYW5kZW4uDQoNCiogTnVuIHp1IFZlcm11dGxpY2ggZGVtIGdyw7bDn3RlbiBQcm9ibGVtIG5lYmVuIGRlbiBiZXJlaXRzIHZvcmhlcmlnIGV0d8OkaG50ZW4gZmVobGVuZGVuIERhdGVuLiBWaWVsZSBzcGllbGUgd2VyZGVuIGF1ZiB2ZXJzY2hpZWRlbmVuIFBsYXRmb3JtZW4sIHp1bSB0ZWlsIGF1ZiBLb25rdXJyZW50ZW4gb2RlciBuYWNoZm9sZ2VybiByZXJlbGVhc3QuIERhcyBiZWRldXRldCBkYXMgZWluIFNwaWVsIGbDvHIgbWVocmVyZSBLb25zb2xlbiB2ZXLDtmZmZW50bGljaHQgd2lyZC4gRGllc2UgRGF0ZW4gd2VyZGVtIGltIFZvcmhhbmRlbmVuIERhdGVuc2F0em5pY2h0IHp1c2FtbWVuZ2Vmw7xocnQgdW5kIGtvbW1lbiBkZW1lbnRzcHJlY2hlbmQgbWVocm1hbHMgdm9yLiBTdXBlciBNYXJpbyBicm9zIGV4aXN0aWVydCBiZWlzcGllbHN3ZWlzZSAxMyBtYWwgdW5kIEdyYW5kIFRoZWZ0IEF1dG8gNCBiZWxlZ3QgcGxhdHogNTIgYXVmIGRlciB4Ym9YMzYwIHVuZCBQbGF0eiA1NyBhdWYgZGVyIFBTMy4NCg0KIyBMaXRlcmF0dXIgdW5kIFF1ZWxsZW52ZXJ6ZWljaG5pcyB7I0xpdGVyYXR1cnZlcnplaWNobmlzfQ0KDQoqIFtMb2dvIGRlciBBcmJlaXRdKGh0dHBzOi8vZGUud2lraXBlZGlhLm9yZy93aWtpL1ZpZGVvX0dhbWVzIy9tZWRpYS9EYXRlaTpWaWRlb2dhbWVzMTk5MS0wMV8obG9nbykuc3ZnKQ0KKiBbRGF0ZW5zYXR6XShodHRwczovL3d3dy5rYWdnbGUuY29tL2RhdGFzZXRzL2dyZWdvcnV0L3ZpZGVvZ2FtZXNhbGVzICkNCiogW3Bsb3RseV0oaHR0cHM6Ly9wbG90bHkuY29tL3IvKQ0KKiBbVmlkZW8gR2FtZSBTdGF0aXN0aWsgMV0oaHR0cHM6Ly93d3cuc3RhdGlzdGEuY29tL3N0YXRpc3RpY3MvMjkzMzA0L251bWJlci12aWRlby1nYW1lcnMvIzp+OnRleHQ9SW4lMjB0b3RhbCUyQyUyMHRoZXJlJTIwd2VyZSUyMGFuLGJpbGxpb24lMjBnYW1lcnMlMjBhY3Jvc3MlMjB0aGUlMjBnbG9iZSkNCiogW1ZpZGUgR2FtZSBTdGF0aXN0aWsgMl0oaHR0cHM6Ly9kZS5zdGF0aXN0YS5jb20vaW5mb2dyYWZpay8yMjQxNC91bXNhdHotYXVzZ2V3YWVobHRlci1zZWt0b3Jlbi1kZXItdW50ZXJoYWx0dW5nc2luZHVzdHJpZSkNCiogW1JfTWFya2Rvd24gMV0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvYm9va2Rvd24vKQ0KKiBbUl9NYXJrZG93biAyXShodHRwczovL2hvbHR6eS5naXRodWIuaW8vUGltcC1teS1ybWQvKQ0KKiBbR2l0aHViIFZlcnplaWNobmlzIGlua2x1c2l2ZSBrb21wbGV0dGVuIFByb2pla3R2ZXJsYXVmc10oaHR0cHM6Ly9naXRodWIuY29tL0pvZHNkZXJlY2h0ZS9SX1N0dWRpb19EZWZhdWx0X3dvcmtzcGFjZSk=
 

Created by Florian Reichle

flre0005@hs-kl.de